WEBARCHIVE File Documentation


Summary

A Safari Web Archive is a saved web page created by Apple’s Safari browser that bundles the HTML together with its images, CSS and scripts inside one file for offline reading. The file is an Apple binary property list (bplist00), not HTML, and its MIME type is application/x-webarchive. A .webarchive opens natively only in Safari on macOS or iOS; on Windows there is no viewer, so it is converted to PDF or HTML.

Technical details

FeatureValue
Full nameSafari Web Archive
File extension.webarchive
MIME typeapplication/x-webarchive
Format typeBinary property list (bplist) bundling a page and its resources
DeveloperApple (WebKit)
Introduced2005, Safari 2.0 / Mac OS X 10.4 Tiger
Open standardNo — proprietary, no published specification
Container / base formatApple binary property list, version 00
SerializationObject table + offset table + 32-byte trailer
Byte orderBig-endian integers within the bplist
Magic number62 70 6C 69 73 74 30 30 (“bplist00”) at offset 0
Top-level keysWebMainResource, WebSubresources
Per-resource keysWebResourceData, WebResourceURL, WebResourceMIMEType
Active contentEmbedded JavaScript runs when opened in WebKit
Native openerSafari (macOS / iOS), Quick Look preview
Cross-platform equivalentsMHTML (.mht/.mhtml), single-file HTML, PDF
Related extensions.plist, .mht, .mhtml, .html, .maff
File signature (magic bytes)
62 70 6C 69 73 74 30 30

Offset 0, 8 bytes, ASCII bplist00. This is the header of an Apple binary property list, version 00 — the same serialization macOS uses for system preferences. It is not an HTML or web signature: the page and its resources are stored as encoded plist objects, not readable markup. Older or exported archives may instead be an XML plist beginning <?xml with a <!DOCTYPE plist…>, in which case there is no fixed binary magic at offset 0.

What is a webarchive file?

A .webarchive file is a single-file copy of a web page saved by Apple’s Safari browser. Apple introduced it in Safari 2.0 in 2005, shipped with Mac OS X 10.4 Tiger, so that a user could keep a whole page — text, images, stylesheets and scripts — in one file for offline reading. A saved HTML file references its images and CSS as separate files that must travel alongside it; a webarchive instead embeds every one of those resources inside the container, each stored with the URL it was fetched from and its MIME type.

The important technical fact is that a webarchive is not a web format at all. It is an Apple binary property list (bplist), the same serialization Apple uses for .plist preference files, holding a tree of dictionaries and byte blobs. Because that structure is tied to Apple’s WebKit engine and has no published specification, the format is effectively proprietary, which is why it opens cleanly in Safari and almost nowhere else. Everything below describes how the page is packed into that plist.

The bplist00 container: header, objects, offsets, trailer

Every binary property list, and therefore every webarchive, is laid out in four regions. It opens with the eight-byte magic bplist00 (62 70 6C 69 73 74 30 30), where the trailing two bytes are the format version. After the header comes the object table, in which each value — a dictionary, a string, an integer, a boolean or a raw data blob — is encoded and concatenated. A single leading marker byte on each object identifies its type and size (for example 0xD introduces a dictionary, 0xA an array, 0x4 a data blob).

Region          Contents
--------------  ---------------------------------------------
Header          "bplist00"  (8 bytes, magic + version)
Object table    every value, encoded back-to-back
Offset table    file offset of each object, fixed-width ints
Trailer         final 32 bytes: sizing + root object index

After the objects comes the offset table: the absolute file offset of every object, each written as a fixed-width big-endian integer. It can only be built after the objects are written, so it sits just before the end of the file. The final 32-byte trailer ties everything together: it records how many bytes each offset-table entry uses, how many bytes an object reference uses, the total number of objects, the index of the root object (normally 0), and the file offset where the offset table begins. A parser reads the trailer first, walks back to the offset table, then decodes the root object and follows references outward. All integers in the structure are big-endian.

WebMainResource and WebSubresources

The root object of a webarchive is a dictionary with two keys. WebMainResource holds the primary document — the HTML page itself — and WebSubresources holds an array of every dependent resource the page loaded. Each of these is itself a dictionary describing one fetched resource:

WebMainResource (dictionary)
 ├─ WebResourceData          raw bytes of the HTML document
 ├─ WebResourceURL           original absolute URL of the page
 ├─ WebResourceMIMEType      e.g. "text/html"
 ├─ WebResourceTextEncodingName   e.g. "UTF-8"
 └─ WebResourceFrameName     "" for the top frame

WebSubresources (array of dictionaries)
 ├─ [0] WebResourceData / URL / MIMEType   (an image)
 ├─ [1] WebResourceData / URL / MIMEType   (a stylesheet)
 └─ [2] WebResourceData / URL / MIMEType   (a script) ...

The value under WebResourceData is a raw data blob: the exact bytes WebKit received when it fetched that resource, whether that is UTF-8 HTML, a PNG image, or minified JavaScript. Alongside it, WebResourceURL preserves the address the resource came from, and WebResourceMIMEType records its content type so WebKit can hand each blob to the right decoder without re-fetching anything. Some archives also nest a WebResourceResponse entry, itself a small embedded property list, carrying the original HTTP response headers. When Safari reopens the file, it reconstructs the page by mapping each embedded resource back onto the URL the HTML expects, so the page renders offline exactly as it was captured. Frames and iframes are captured as additional main-resource dictionaries so a multi-frame page survives intact.

Reading a webarchive outside the Apple ecosystem

Because the payload is a standard binary property list, the file can be decoded by any plist library even without Safari. On macOS the plutil -convert xml1 command rewrites a binary webarchive as a readable XML plist; Python’s plistlib parses it into nested dictionaries from which each WebResourceData blob can be written back out to a real file. That is exactly how third-party converters recover the HTML and images: they walk the WebMainResource and WebSubresources tree and reassemble a folder of ordinary web files, or render the page to PDF. What no non-WebKit tool does is display the archive natively, because rendering it means running WebKit’s full page-loading path against the embedded resources.

The cross-platform equivalents solve the same “one page, one file” problem with open formats. MHTML (.mht/.mhtml), which Chrome and Edge save, packs the page as a MIME multipart message — the same envelope as an email — rather than a plist, and printing a page to PDF flattens it entirely. Both are portable in a way .webarchive is not.

Frequently asked questions

Why can’t Chrome or Firefox open a webarchive?

A .webarchive is an Apple binary property list produced by WebKit, not an HTML or MHTML file, and no published specification exists for it. Chrome, Edge and Firefox have no code to parse the plist or reconstruct the page from its WebResourceData blobs, so they cannot open it. Those browsers use MHTML (.mht) for single-file saved pages instead.

How is the page actually stored inside the file?

The HTML lives under the WebMainResource dictionary as a raw WebResourceData blob, with its URL, MIME type and text encoding beside it. Every image, stylesheet and script is a separate dictionary in the WebSubresources array, each keeping its own bytes, original URL and MIME type. A plist library can read the file and write each blob back out as a normal file.

References