ByteScope

JSON file format

JavaScript Object Notation, a lightweight structured data format.

MIME type
application/json
Extensions
.json
Category
Text & markup

Magic-number signature

Text starting with '{' or '[' followed by a quoted key or nested bracket.

About the JSON format

JSON is the subset of JavaScript object-literal syntax that Douglas Crockford wrote down rather than invented, and the whole specification fits comfortably on a few pages. It has six types - object, array, string, number, boolean and null - and no date, no binary, no comment and no version. Every one of those omissions is deliberate, and every one of them is worked around somewhere: dates become ISO strings, binary becomes base64, comments become a key nobody reads, versioning becomes a field the reader has to remember to check. That combination of a tiny grammar and universal support is why it won, and it is also why almost every practical JSON problem is about something the format does not say.

Header layout, byte by byte

OffsetLengthFieldMeaning
01First structural character7B for an object or 5B for an array, after any leading whitespace. The current standard allows a JSON text to be any value at all, so a bare number or a quoted string is legal too, but the superseded 2006 specification permitted only objects and arrays and virtually every producer alive still emits one of those two.
04Encoding-detection windowBecause the first two characters of a JSON text are always ASCII, the pattern of nulls in the first four bytes identifies the encoding: 00 00 00 xx is UTF-32 big-endian, 00 xx 00 xx is UTF-16 big-endian, xx 00 00 00 is UTF-32 little-endian, xx 00 xx 00 is UTF-16 little-endian, and four non-null bytes are UTF-8. Modern JSON must be UTF-8 on the wire, so in practice this test tells you what went wrong rather than what to do.
03UTF-8 byte-order markEF BB BF. The standard says an implementation must not add one and permits a parser to ignore one; the JavaScript engines behind Node and the browsers do neither and throw on it, which makes a mark added by a Windows editor a routine reason a hand-edited config file stops loading with no visible change to its text.
31First structural character behind a markWhere the document really begins when a mark is present. Worth stating on its own, because the error a parser reports names an unexpected token at position 0 and the character at position 0 is invisible in every editor that will be used to look for it.
0variableEverything elseThere is no header. No magic number, no length, no version, no checksum, no trailer, no index. A JSON file is content from its first byte to its last, and every property a reader might want to know - how big it is, whether it is complete, what shape it has - can only be obtained by parsing all of it.

Telling it apart from its neighbours

Easily confused withHow to tell
NDJSON/JSON LinesByte-identical at the front - an opening brace either way. The difference is that JSON Lines puts one complete document on each line, with no enclosing array and no commas between them, so a standard parser reads the first line successfully and then fails on the second with an unexpected character after the end of the JSON. Log pipelines and dataset dumps use it precisely because it can be appended to and read one line at a time.
JSONC / JSON5Also identical at offset 0, and invalid the moment you reach the first // comment or trailing comma. tsconfig.json and the settings files of several editors are JSONC and are not JSON, which is why a program that reads them with a strict parser fails on a file the editor that wrote it accepts without comment.
XMLA brace or a bracket against an angle bracket, so telling them apart is trivial. The comparison that actually matters is what they are for: JSON has exactly one way to express a list and no way at all to express text with markup inside it, which is why data moved to JSON and documents did not.
CBOR/MessagePack/BSONBinary encodings of nearly the same data model, and none of them are text. CBOR writes a map as a single leading byte in the range A0 to BF; BSON begins with a little-endian 32-bit total length, so its first byte is usually small and unprintable. If a file that should be JSON opens as binary, one of these is the likely answer and nothing at all is damaged.
JSONPA callback name and an opening parenthesis in front of the object - an executable JavaScript statement rather than a data document. The rule is simple enough to apply from the first byte: anything starting with a letter is not JSON.

How these files break

  • Truncation. There is no length and no trailer, so a document cut short fails with an unexpected end of input and no way to tell how much is missing. Streams written without a final flush lose the closing brace and nothing else, which is why the repair that works most often is simply appending one.
  • A byte-order mark. Three bytes no editor displays, in front of a file that is otherwise perfect, producing a parse error that names position 0. Checking the first three bytes in a hex viewer settles in seconds what can otherwise cost an afternoon.
  • Trailing data. Two documents concatenated, or a log line appended to a file, gives an unexpected non-whitespace character after the JSON at a stated position - and that position is counted in characters of the decoded text, not in bytes, so on any file containing non-ASCII it will not line up with a hex editor's cursor.
  • Numbers that come back as different numbers. The format has one number type and states no precision, and readers built on IEEE 754 doubles agree exactly only on integers between minus 2 to the 53rd plus one and 2 to the 53rd minus one. An identifier of 9007199254740993 read and written back becomes 9007199254740992, with no error raised anywhere: the bytes on disk were right and the value in memory was not. Systems that hit this ship identifiers as strings from then on.
  • Lone surrogates. A string containing an escape such as \uD800 with no pairing escape after it parses successfully, because the grammar accepts any four hex digits, and then cannot be written back out as valid UTF-8. What emerges on the far side is a replacement character, so the data is quietly different after a round trip that reported success at every step.

Where the format stands today

JSON is the default data format of everything networked, and its position is not seriously contested. REST and GraphQL both speak it, package manifests and lock files are written in it, log pipelines emit a document per line, and every language ships a parser in its standard library. Where it is deliberately not used is more telling than where it is. Configuration keeps drifting to YAML and TOML because JSON has no comments and no trailing commas, which are ergonomic complaints rather than technical ones and are none the less decisive. High-volume internal traffic moves to Protocol Buffers, CBOR or MessagePack, because parsing text costs more than parsing a length-prefixed binary and having a schema is worth the build step. Very large tabular data goes to Parquet, because JSON repeats every key on every row. What keeps JSON first choice is that a person can read it: for an API someone else has to integrate against, for a config file someone will edit at three in the morning, and for anything that will be debugged by looking at it, the inefficiency is simply the price of being self-explanatory in a terminal.

Open JSON files on this site

Every one of these runs in your browser — the file never leaves your machine.

Related formats

Formats that are easy to confuse with JSON — compare their leading bytes.

FormatFirst bytesExtension
XMLno fixed signature.xml
HTMLno fixed signature.html

Frequently asked questions

What is a magic number in a file?

The first few bytes of a file, which identify its format regardless of what the name says. A PNG always starts with 89 50 4E 47; a ZIP with 50 4B 03 04. Operating systems, browsers and the file command all read these bytes rather than trusting the extension, which is why renaming a file does not change what it actually is.

How do I check a file's magic number myself?

On macOS or Linux, xxd -l 16 yourfile prints the first 16 bytes; on Windows, Format-Hex -Path yourfile -Count 16 in PowerShell. Or drop the file into the File Type Identifier on this site, which reads the bytes locally and names the format for you — nothing is uploaded.

Why do two formats share the same magic number?

Because one is built on the other. Every docx, xlsx, pptx, apk, jar and epub begins with the ZIP signature, since all of them are ZIP archives underneath; telling them apart means looking at the entries inside. Java class files and macOS universal binaries both start with CA FE BA BE and are distinguished by the field that follows.

Can a file have no magic number at all?

Yes. Text-based formats — XML, HTML, JSON, SVG, CSV — have no fixed byte signature, so they are recognized structurally instead: a leading <?xml declaration, a <svg element, or a { followed by a quoted key. That detection is a good guess rather than a certainty, which is why this reference marks those formats as probe-detected.

Does a matching magic number mean the file is safe?

No. It tells you what the format is, not whether the contents are harmless — a genuine PDF or docx can still carry a malicious payload. Identifying the true type is a useful first check, especially when the extension disagrees with the bytes, but it is not a malware scan.

Have a file that might be in the JSON format? Identify it with the File Type Identifier — it reads the magic number locally, nothing is uploaded. Or browse all formats.