Skip to content
LocalOnly
JSON Tools

How to Measure JSON Size: Characters, Bytes and Gzip

A payload can be 19,847 characters, 20,197 bytes and 1,803 bytes on the wire, all at once. Here is which number an API limit, a database or a browser actually checks.

Updated October 18, 20263 min readTool runs in your browser

To measure JSON size in bytes, first decide which size you mean. Ask how big a JSON payload is and there are three honest answers: how many characters it has, how many bytes it takes in UTF-8, and how many bytes it takes once compressed. For a sample list of 200 orders with customer names in several languages, those were 19,847 characters, 20,197 bytes and 1,803 gzip bytes.

Limits are written against one of those numbers, and measuring the wrong one is how a payload that looked small enough in a test gets rejected later. The JSON Statistics tool profiles a document's structure; this guide is about its size.

String length is not byte length

In JavaScript, string.length counts UTF-16 code units, not characters and not bytes. ASCII text has the same length and byte count, and anything else does not:

Text      .length   UTF-8 bytes
hello     5         5
é         1         2
€         1         3
👍        2         4
日本語     3         9

The emoji has a length of 2 because it needs two UTF-16 code units. Even é is not fixed: written as one composed character it has length 1, but decomposed into e plus a combining accent, as some keyboards and macOS file names produce, it has length 2.

Languages also disagree on length. For the JSON text {"name":"José","note":"👍"}, JavaScript and Java report a length of 27, because both count UTF-16 code units, while Python reports 26, because it counts code points. All three agree that it is 30 bytes in UTF-8.

The same data serialises to different sizes

Python's json.dumps escapes every non-ASCII character by default, so its output is larger than JavaScript's for the same data:

Value     json.dumps (default)        bytes   ensure_ascii=False   bytes
é         "\u00e9"                     8       "é"                   4
👍        "\ud83d\udc4d"               14      "👍"                  6
日本語     "\u65e5\u672c\u8a9e"         20      "日本語"               11

For text-heavy data in non-Latin scripts, the default output can be close to twice the size. Both forms are valid JSON and parse to the same strings, but a size limit sees the difference.

Which number to use

  • Limits on request bodies, files and stored records almost always count UTF-8 bytes of the uncompressed text. Compressing a request does not always help either: Express, for example, applies its body limit after decompressing.
  • Transfer time and bandwidth depend on the compressed bytes. HTTP Content-Length describes the body as sent: a 7,991-byte JSON response sent with gzip carried Content-Length: 730.
  • Text field limits, such as a maximum length for a name, count characters, and as shown above, languages disagree on what a character is. Check which unit the validating side uses.

Measure JSON size in bytes in code

JavaScript
const json = JSON.stringify(payload);
Buffer.byteLength(json);                  // Node
new TextEncoder().encode(json).length;    // browsers and Node
new Blob([json]).size;                    // browsers and Node
Python
json_text = json.dumps(payload, ensure_ascii=False, separators=(",", ":"))
len(json_text.encode("utf-8"))
Java
json.getBytes(StandardCharsets.UTF_8).length

Measure exactly what you send. If the client minifies, measure the minified text. If Python sends with the default ensure_ascii, measure that output, not a version with ensure_ascii=False. For the compressed size, compress it: gzipSync(json).length in Node or len(gzip.compress(data)) in Python.

Frequently asked questions

Command Palette

Search for a tool or command