Task 281: .HAR File Format
Task 281: .HAR File Format
1. List of All Properties Intrinsic to the .HAR File Format
The .HAR (HTTP Archive) format is a JSON-based structure with no binary headers, magic numbers, or traditional file system metadata (e.g., no embedded files, compression layers, or directory structures like ZIP). It is a plain UTF-8 text file containing a single JSON object. The "intrinsic properties" refer to the defined fields in the JSON schema, which form the hierarchical structure for logging HTTP data. Below is a comprehensive list of all properties from the HAR 1.2 specification, grouped by object for clarity. Each includes type and brief description. Optional properties are marked.
Root log
Object (Required)
version
(string, required): Format version (e.g., "1.2").creator
(object, required): Creator application details.name
(string, required): Application name.version
(string, required): Application version.comment
(string, optional): Comment.browser
(object, optional): Browser details.name
(string, required if present): Browser name.version
(string, required if present): Browser version.comment
(string, optional): Comment.pages
(array ofpage
objects, optional): List of tracked pages.entries
(array ofentry
objects, required): List of HTTP requests.comment
(string, optional): Overall comment.
page
Object (Within pages
)
startedDateTime
(string, required): Page load start time (ISO 8601).id
(string, required): Unique page ID.title
(string, required): Page title.pageTimings
(object, required): Page load timings.onContentLoad
(number, optional): Time to content load (ms, -1 if N/A).onLoad
(number, optional): Time to full load (ms, -1 if N/A).comment
(string, optional): Comment.comment
(string, optional): Comment.
entry
Object (Within entries
)
pageref
(string, optional): Reference to parent page ID.startedDateTime
(string, required): Request start time (ISO 8601).time
(number, required): Total request time (ms).request
(object, required): Request details.method
(string, required): HTTP method (e.g., "GET").url
(string, required): Full URL.httpVersion
(string, required): HTTP version (e.g., "HTTP/1.1").cookies
(array ofcookie
objects, optional): Request cookies.headers
(array ofheader
objects, optional): Request headers.queryString
(array ofqueryParam
objects, optional): Query parameters.postData
(object, optional): POST data.headersSize
(number, required): Request headers size (bytes, -1 if N/A).bodySize
(number, required): Request body size (bytes, -1 if N/A).comment
(string, optional): Comment.response
(object, required): Response details.status
(number, required): HTTP status code.statusText
(string, required): Status text.httpVersion
(string, required): HTTP version.cookies
(array ofcookie
objects, optional): Response cookies.headers
(array ofheader
objects, optional): Response headers.content
(object, required): Response content.redirectURL
(string, required): Redirect URL.headersSize
(number, required): Response headers size (bytes, -1 if N/A).bodySize
(number, required): Response body size (bytes, -1 if N/A).comment
(string, optional): Comment.cache
(object, optional): Cache info.beforeRequest
(object, optional): Cache state before request.expires
(string, optional): Expiration time (ISO 8601).lastAccess
(string, optional): Last access time (ISO 8601).eTag
(string, optional): ETag.hitCount
(number, optional): Hit count.size
(number, optional): Size (bytes).afterResponse
(object, optional): Cache state after response (same subproperties asbeforeRequest
).comment
(string, optional): Comment.timings
(object, required): Timing phases (ms, -1 if N/A).blocked
(number, optional): Queue time.dns
(number, optional): DNS resolution time.connect
(number, optional): Connection time.send
(number, optional): Send time.wait
(number, optional): Wait time.receive
(number, optional): Receive time.ssl
(number, optional): SSL negotiation time.comment
(string, optional): Comment.serverIPAddress
(string, optional): Server IP.connection
(string, optional): Connection ID.comment
(string, optional): Comment.
Common Sub-Objects
cookie
(object):name
(string, required): Cookie name.value
(string, required): Cookie value.path
(string, optional): Path.domain
(string, optional): Domain.expires
(string, optional): Expiration (ISO 8601).httpOnly
(boolean, optional): HTTP-only flag.secure
(boolean, optional): Secure flag.comment
(string, optional): Comment.header
(object):name
(string, required): Header name.value
(string, required): Header value.comment
(string, optional): Comment.queryParam
(object):name
(string, required): Parameter name.value
(string, required): Parameter value.comment
(string, optional): Comment.postData
(object, withinrequest
):mimeType
(string, required if present): MIME type.params
(array of{name: string, value: string, comment?: string}
, optional): Parameters.text
(string, optional): Raw text (mutually exclusive withparams
).comment
(string, optional): Comment.content
(object, withinresponse
):size
(number, required): Content size (bytes).compression
(number, optional): Compression savings (bytes).mimeType
(string, required): MIME type.text
(string, optional): Response text (decoded or encoded).encoding
(string, optional): Text encoding (e.g., "base64").comment
(string, optional): Comment.
2. Two Direct Download Links for .HAR Files
- Sample HAR file for igvita.com (JSON content, save as .har): https://gist.githubusercontent.com/igrigorik/3495174/raw/igvita.har.json
- Sample HAR file for menadevs.com: https://storage.googleapis.com/thecodeship/menadevs.com.har
3. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .HAR Parsing
Embed this as a custom HTML card in Ghost (via the editor's HTML block). It creates a drag-and-drop zone that parses the uploaded .HAR file (JSON) and dumps all properties recursively to a <pre>
element on screen.
Drag and drop a .HAR file here to view properties
4. Python Class for .HAR Handling
This class reads a .HAR file, decodes (parses JSON), prints all properties recursively to console, and supports writing back to a new .HAR file.
import json
import sys
class HARHandler:
def __init__(self, filepath=None):
self.data = None
if filepath:
self.read(filepath)
def read(self, filepath):
"""Read and decode .HAR file."""
with open(filepath, 'r', encoding='utf-8') as f:
self.data = json.load(f)
self._print_properties(self.data, 'log')
def write(self, filepath):
"""Write data back to .HAR file."""
if not self.data:
raise ValueError("No data to write.")
with open(filepath, 'w', encoding='utf-8') as f:
json.dump(self.data, f, indent=2, ensure_ascii=False)
def _print_properties(self, obj, path=''):
"""Recursively print all properties to console."""
if isinstance(obj, dict):
for key, value in obj.items():
new_path = f"{path}.{key}" if path else key
print(f"{new_path}: {value}")
self._print_properties(value, new_path)
elif isinstance(obj, list):
for idx, item in enumerate(obj):
new_path = f"{path}[{idx}]"
print(f"{new_path}: {type(item).__name__} (array item)")
self._print_properties(item, new_path)
else:
print(f"{path}: {obj}")
# Example usage:
# handler = HARHandler('sample.har')
# handler.write('output.har')
5. Java Class for .HAR Handling
This class uses Jackson library (add com.fasterxml.jackson.core:jackson-databind:2.15.0
to your project). It reads, decodes, prints properties recursively to console, and writes back.
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class HARHandler {
private JsonNode data;
public HARHandler(String filepath) throws IOException {
ObjectMapper mapper = new ObjectMapper();
this.data = mapper.readTree(new File(filepath));
printProperties(data, "log");
}
public void write(String filepath) throws IOException {
if (data == null) throw new IllegalStateException("No data to write.");
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(new File(filepath), data);
}
private void printProperties(JsonNode node, String path) {
if (node.isObject()) {
node.fields().forEachRemaining(entry -> {
String key = entry.getKey();
JsonNode value = entry.getValue();
String newPath = path.isEmpty() ? key : path + "." + key;
System.out.println(newPath + ": " + value);
printProperties(value, newPath);
});
} else if (node.isArray()) {
for (int i = 0; i < node.size(); i++) {
String newPath = path + "[" + i + "]";
System.out.println(newPath + ": " + node.get(i).getNodeType() + " (array item)");
printProperties(node.get(i), newPath);
}
} else {
System.out.println(path + ": " + node.asText());
}
}
public static void main(String[] args) throws IOException {
if (args.length > 0) {
HARHandler handler = new HARHandler(args[0]);
// handler.write("output.har");
}
}
}
6. JavaScript Class for .HAR Handling
This Node.js class (uses fs
module) reads, decodes, prints properties recursively to console, and writes back. Run with Node.js.
const fs = require('fs');
class HARHandler {
constructor(filepath = null) {
this.data = null;
if (filepath) {
this.read(filepath);
}
}
read(filepath) {
const content = fs.readFileSync(filepath, 'utf8');
this.data = JSON.parse(content);
this._printProperties(this.data, 'log');
}
write(filepath) {
if (!this.data) throw new Error('No data to write.');
fs.writeFileSync(filepath, JSON.stringify(this.data, null, 2), 'utf8');
}
_printProperties(obj, path = '') {
if (obj === null || typeof obj !== 'object') {
console.log(`${path}: ${obj}`);
return;
}
if (Array.isArray(obj)) {
obj.forEach((item, idx) => {
const newPath = `${path}[${idx}]`;
console.log(`${newPath}: ${typeof item} (array item)`);
this._printProperties(item, newPath);
});
} else {
Object.entries(obj).forEach(([key, value]) => {
const newPath = path ? `${path}.${key}` : key;
console.log(`${newPath}: ${value}`);
this._printProperties(value, newPath);
});
}
}
}
// Example usage:
// new HARHandler('sample.har');
// handler.write('output.har');
7. C Class (Struct) for .HAR Handling
This uses the cJSON library (download from https://github.com/DaveGamble/cJSON). Compile with: gcc -o har_handler har_handler.c -lcjson
. It reads, decodes (parses JSON), prints properties recursively to stdout, and writes back.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
typedef struct {
cJSON *data;
} HARHandler;
HARHandler *har_handler_new(const char *filepath) {
FILE *f = fopen(filepath, "r");
if (!f) return NULL;
fseek(f, 0, SEEK_END);
long len = ftell(f);
fseek(f, 0, SEEK_SET);
char *buf = malloc(len + 1);
fread(buf, 1, len, f);
buf[len] = '\0';
fclose(f);
HARHandler *handler = malloc(sizeof(HARHandler));
handler->data = cJSON_Parse(buf);
free(buf);
if (handler->data) {
print_properties(handler->data, "log");
}
return handler;
}
void har_handler_free(HARHandler *handler) {
if (handler) {
cJSON_Delete(handler->data);
free(handler);
}
}
void write_har(HARHandler *handler, const char *filepath) {
if (!handler || !handler->data) return;
char *json_str = cJSON_Print(handler->data);
FILE *f = fopen(filepath, "w");
if (f) {
fputs(json_str, f);
fclose(f);
}
free(json_str);
}
void print_properties(cJSON *node, const char *path) {
if (!node) return;
if (cJSON_IsObject(node)) {
cJSON *child;
cJSON_ArrayForEach(child, node) {
char new_path[1024];
snprintf(new_path, sizeof(new_path), "%s%s%s", path, strlen(path) ? "." : "", child->string);
printf("%s: %s\n", new_path, cJSON_Print(child));
print_properties(child, new_path);
}
} else if (cJSON_IsArray(node)) {
int i = 0;
cJSON *child;
cJSON_ArrayForEach(child, node) {
char new_path[1024];
snprintf(new_path, sizeof(new_path), "%s[%d]", path, i++);
printf("%s: %s (array item)\n", new_path, cJSON_GetStringValue(child) ? cJSON_GetStringValue(child) : "object");
print_properties(child, new_path);
}
} else {
printf("%s: %s\n", path, cJSON_PrintUnformatted(node));
}
}
int main(int argc, char **argv) {
if (argc > 1) {
HARHandler *handler = har_handler_new(argv[1]);
if (handler) {
// write_har(handler, "output.har");
har_handler_free(handler);
}
}
return 0;
}