The HAR file format, field by field
A HAR file looks like a wall of JSON because that's exactly what it is: one log object, laid out by the never-quite-finalized HAR 1.2 spec, holding everything a browser did on the network. Once you know the five keys that matter, the wall becomes a table of contents.
Want one to poke at while reading? Download our sample HAR file — five requests including a login POST, a 404 and a slow endpoint — or watch the same structure rendered as a waterfall.
The top level: log, pages, entries
log.version is almost always 1.2, and log.creator names whatever recorded the file — Chrome DevTools, Firefox, a proxy. log.pages lists the page loads, each with an id, title and startedDateTime. Then log.entries is the array you actually care about: one object per HTTP request, linked back to its page by pageref.
Anatomy of an entry
Every entry carries startedDateTime (ISO 8601) and time (total milliseconds), plus a request and a response object. Both sides share the same shape: httpVersion, a headers array of {name, value} pairs, and a cookies array. The request adds method, url, queryString and optional postData; the response adds status, statusText and content — which is where bodies live, as content.text with content.encoding set to base64 when the payload isn't UTF-8 text.
The timings object is the waterfall
timings breaks each request into blocked, dns, connect, ssl, send, wait and receive — the seven bars DevTools draws. wait is server thinking time, receive is download time, and ssl is a slice of connect, not an addition to it. A -1 means "not applicable": a cache hit has no DNS or connect phase. The entry's top-level time should equal the sum of the non-negative parts.
Quirks that break naive parsers
Headers repeat — Set-Cookie appears once per cookie, so last-write-wins maps destroy data. Sizes disagree: content.size is decoded bytes while the unofficial _transferSize is compressed on-the-wire bytes. Anything prefixed with _ is a vendor extension, not the spec. And pages can be an empty array with pageref missing entirely, so parsers that assume every entry has a page die on perfectly valid files.
Parsing it yourself
It's plain JSON, so JSON.parse gets you ninety percent there — the remaining ten is size. Real captures run to hundreds of megabytes, so stream or pre-filter before doing anything fancy. If you just need structured data out of a file right now, the HAR viewer API parses, summarizes and sanitizes over HTTP, and the interactive viewer draws the same entries as a timings waterfall.
HAR Viewer
See this structure rendered as a waterfall — with automatic failure and secret detection
Frequently asked questions
What does HAR stand for?
HTTP Archive. The format was created around 2009 by Jan Odvarko of Firebug fame, and the 1.2 draft spec from 2012 is still the version every browser writes today.
Is a HAR file valid JSON?
Yes — a single JSON object with a log key at the top, no comments, no trailing data. If JSON.parse rejects it, the file is truncated or isn't a HAR at all.
Why is the response body in base64?
When the body isn't valid UTF-8 text — images, fonts, compressed downloads — exporters store it with content.encoding set to base64. Decode the text field accordingly to recover the original bytes.
Where can I download a sample HAR file?
Right here: our example.har has five requests covering a page load, a login POST with cookies, an authenticated API call, a slow endpoint and a 404 — small enough to read by hand, realistic enough to test a parser against.