Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

JSON is one serialized value, while JSONL (JSON Lines) is a sequence of JSON values separated by line endings. Use JSON for a single document—usually an object or an array—such as an API request, response, or configuration file. Use JSONL when independent records should be appended, streamed, piped through command-line tools, or processed one at a time. A JSON array can hold many records, but it is still one JSON document; JSONL makes every record a separate JSON text.

JSONL vs. JSON at a glance

Decision point JSON JSONL / NDJSON
Top-level organization One JSON value: object, array, string, number, Boolean, or null A sequence of JSON values, conventionally one per line
Typical processing Parse the document as a whole, or use a parser that supports incremental input Read, validate, and handle each record as it arrives
Appending Adding to an array requires preserving commas, brackets, and valid document syntax Appending a new line is simple, subject to file-locking and concurrency rules
Common uses API payloads, configuration, nested documents, browser and application data Logs, bulk records, shell pipelines, streams, and process-to-process messages
Registered or recommended media type application/json is registered by RFC 8259 JSON Lines documentation mentions application/jsonl but it is not standardized; NDJSON recommends application/x-ndjson

These are format-level tendencies, not promises about memory usage or streaming support. A particular API or parser may accept only one format, buffer an entire response, or impose its own schema and delimiter rules.

What JSON means

RFC 8259 defines JavaScript Object Notation as a text format for serializing structured data. A JSON text is one serialized value. Most application examples use an object, such as {"id":42,"status":"ready"}, or an array, such as [{"id":1},{"id":2}]. The standard also permits a top-level string, number, Boolean, or null.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

An object is an unordered collection of name/value pairs. An array is an ordered sequence of values, and its elements may themselves be objects or arrays. This nesting is why JSON works well for a complete response that contains metadata, a set of records, and related child objects in one document.

Because the document has one root value, a consumer can validate the complete structure before using it. That is useful when the operation should either succeed for the whole payload or fail as a unit—for example, a configuration file or a request whose fields are mutually dependent.

What JSONL and NDJSON mean

JSON Lines is a convention for a text file or stream containing multiple JSON values, with one value per line. The NDJSON 1.0.0 specification makes the boundary explicit: each JSON text is followed by a line-feed character (n), with CRLF (rn) also accepted. A record must not contain an unescaped raw newline or carriage-return character.

For example, this is valid JSONL:

{"event":"login","user_id":17}
{"event":"purchase","user_id":17,"total":29.99}
{"event":"logout","user_id":17}

Each line can be parsed independently. A reader can emit the first event before the producer has written the third, and a failed record can be reported without making already-processed records syntactically part of one invalid array. JSONL is therefore convenient for data that naturally arrives as independent events or rows.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

JSONL and NDJSON are often used as synonyms, but their published conventions are not identical in every detail. Match the exact specification, extension, media type, and error behavior required by the receiving software instead of assuming that a label guarantees compatibility.

The differences that affect a design

One document versus many records

A JSON array containing 100,000 objects is one JSON document. The closing bracket is required, commas separate elements, and a strict parser normally considers the document incomplete until it reaches the end. A JSONL file containing the same objects has 100,000 JSON texts, each terminated by a line ending. The distinction is structural, not merely a different filename.

Whole-document validation versus record-level handling

With JSON, validation commonly answers “is this complete document valid?” With JSONL, the application must define what happens when line 438 is malformed: stop immediately, skip it, quarantine it, or continue while recording an error. NDJSON says malformed JSON should cause an error; JSON Lines allows parsers to ignore empty lines only when that behavior is documented by the parser.

Appending and concurrent writers

Appending an object to a JSON array requires changing the document’s closing bracket and managing commas. Appending one JSONL record is a write of another line, but that does not make concurrent writes safe automatically. Use the file-locking, transaction, or queueing mechanism required by your environment so two writers cannot interleave bytes or produce a partial line.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Streaming is possible, but not guaranteed

JSONL exposes natural record boundaries, which makes incremental processing straightforward. It does not force a library, HTTP client, database driver, or API server to stream. Check the actual contract: a service may send JSONL over a streaming response, or it may generate the entire file before transmission.

Media types and extensions

For ordinary JSON, use application/json when that is the contract. JSON Lines documentation notes that application/jsonl is not standardized. NDJSON recommends application/x-ndjson and the .ndjson extension. Some tools use .jsonl instead. Send the media type the recipient documents, not the one that merely looks familiar.

When to choose JSON

  • The payload is one logical document. A profile, configuration tree, API request, or response with metadata and nested children is naturally represented by one root value.
  • Consumers need the complete structure before acting. Whole-document validation and all-or-nothing handling are easier with JSON.
  • The receiver explicitly requires JSON. A format choice cannot override an API’s documented content type or schema.
  • Record order and grouping belong inside the document. Use arrays and object fields when the relationships between values are part of the payload.

For a collection, this shape is valid JSON:

{
  "generated_at": "2026-09-30T12:00:00Z",
  "items": [
    {"id": 101, "state": "ready"},
    {"id": 102, "state": "queued"}
  ]
}

The metadata and records are available together, and the array remains one top-level value.

When to choose JSONL

  • Records are independent. Logs, events, exports, and job results can be handled one record at a time.
  • Input arrives continuously. A producer can write another complete line without rewriting a previous document.
  • You need line-oriented tools. Shell pipelines, text processing utilities, and batch workers can consume one record per line.
  • Partial progress matters. A worker can checkpoint after each valid line rather than waiting for a complete array.
  • Files are naturally append-oriented. JSONL avoids array punctuation, while still requiring an application-level policy for rotation, locking, and recovery.

Do not select JSONL solely because a file may become large. A JSON parser may stream an array, and a JSONL reader may buffer every line. Choose based on the interface and processing contract, then verify the implementation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Working examples: convert and process both formats

Python: write JSON and JSONL

import json

records = [
    {"id": 1, "status": "ready"},
    {"id": 2, "status": "queued"},
]

# One JSON document (an array)
with open("records.json", "w", encoding="utf-8") as f:
    json.dump(records, f, ensure_ascii=False, indent=2)
    f.write("n")

# JSONL: one JSON text per line
with open("records.jsonl", "w", encoding="utf-8", newline="n") as f:
    for record in records:
        f.write(json.dumps(record, ensure_ascii=False) + "n")

Python: read JSONL safely

import json

with open("records.jsonl", encoding="utf-8") as f:
    for line_number, raw in enumerate(f, start=1):
        if raw.strip() == "":
            # Choose this only if your file contract permits blank lines.
            continue
        try:
            record = json.loads(raw)
        except json.JSONDecodeError as exc:
            raise ValueError(f"Malformed JSONL at line {line_number}: {exc}") from exc
        # Process or persist record here.
        print(record["id"])

Node.js: read and write JSONL

import { createReadStream } from 'node:fs';
import { appendFile } from 'node:fs/promises';
import { createInterface } from 'node:readline';

await appendFile('events.jsonl', JSON.stringify({ event: 'started', id: 7 }) + 'n', 'utf8');

const input = createInterface({
  input: createReadStream('events.jsonl', { encoding: 'utf8' }),
  crlfDelay: Infinity
});

let lineNumber = 0;
for await (const line of input) {
  lineNumber += 1;
  if (line.trim() === '') continue;
  try {
    const event = JSON.parse(line);
    console.log(event);
  } catch (error) {
    throw new Error(`Malformed JSONL at line ${lineNumber}: ${error.message}`);
  }
}

These examples deliberately make blank-line behavior explicit. Both JSON Lines and NDJSON require UTF-8, and JSON Lines says a byte-order mark must not be included. If your producer emits a BOM, strips or rejects it according to the receiving contract rather than silently assuming every parser will handle it.

How to design a dependable JSONL contract

  1. Define the record schema. State required fields, types, whether unknown fields are allowed, and whether every line represents the same kind of record.
  2. Define delimiters and encoding. Use UTF-8, document LF or accepted CRLF, and ensure values contain escaped rather than raw newline characters.
  3. Define blank-line behavior. Reject blank lines for strict interchange, or document that readers ignore them.
  4. Define malformed-record recovery. Specify whether the stream stops, the line is skipped, or the line is moved to an error file. Include the line number and original bytes when diagnosing failures.
  5. Define completion and durability. A newline can mark a complete record, but a process crash can still leave a truncated final line. Decide whether consumers wait for a terminating newline and how files are rotated or resumed.
  6. Define ordering and duplicates. If retries can repeat a record, include an idempotency key or sequence field and document whether order is meaningful.

For an HTTP endpoint, document the request and response media types separately. A service may accept application/x-ndjson for uploads while returning ordinary application/json for an error object.

Common mistakes and fixes

Putting several root objects in a JSON file

{"id":1}
{"id":2}

This is not one valid JSON document; it is JSONL. Either send it as a documented line-delimited stream or wrap the values in an array: [{"id":1},{"id":2}].

Adding a trailing comma

JSON arrays and objects do not permit a trailing comma under RFC 8259. In JSONL, each line is parsed independently, so a comma at the end of a line is also invalid unless it is part of a value such as a string.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Embedding a literal newline inside a record

Escape the character as n inside a JSON string. A raw line break terminates the JSONL record and leaves the parser with an incomplete or malformed JSON text.

Assuming every “JSONL” endpoint uses the same content type

Check whether the service requires application/jsonl, application/x-ndjson, or another documented value. The names are widely conflated, but media-type conventions are not universal.

Continuing after an error without a policy

Silently skipping a malformed line can lose data; stopping the entire stream can delay unrelated records. Make the choice explicit, emit an error with the line number, and test recovery with a deliberately malformed record.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

ScreenshotNeo is a separate option when your workflow needs a clean website capture—for example, to create visual fixtures alongside a JSON or JSONL export. It is a website screenshot API and MCP server for developers. One GET request returns a PNG, JPEG, WebP, or PDF; it is not a JSONL transport, so use it for the screenshot step rather than replacing your data format.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

ScreenshotNeo accepts the cookie or consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing; response headers identify the page verdict and whether the request was billed. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo documentation for the complete API contract. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to try the capture endpoint.

FAQ

Can one JSONL line be an array or a scalar?

Yes. Each line is a JSON value, so a line may contain an object, array, string, number, Boolean, or null. Your application should still document the permitted record shape.

Should I use the .jsonl or .ndjson extension?

Use the extension required by the receiving tool. JSON Lines commonly uses .jsonl; NDJSON documentation recommends .ndjson. The extension alone does not establish the parser or media type.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can a JSONL stream contain different record types?

It can, but consumers need a discriminator such as a type field and a schema for each variant. If records are unrelated, separate streams may be easier to validate and operate.

Is JSONL always faster or smaller?

No. Its main advantage is record boundaries and incremental handling. Encoding, indentation, compression, parser behavior, network buffering, and the receiving application’s implementation determine actual speed and size.

Bottom line

Choose JSON when you are exchanging one complete, structured value. Choose JSONL when you are exchanging independent values that should be appended, streamed, piped, or processed record by record. Treat JSONL and NDJSON as closely related conventions, not as a guarantee that every endpoint shares the same media type or error rules; then follow the exact contract published by your reader and writer.

Frequently Asked Questions

Can one JSONL line be an array or a scalar?

Yes. Each line is a JSON value, so it may be an object, array, string, number, Boolean, or null, subject to the application’s documented schema.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should I use the .jsonl or .ndjson extension?

Use the extension required by the receiving tool. The extension alone does not determine parser behavior or media type.

Can a JSONL stream contain different record types?

Yes, if the stream documents a discriminator such as a type field and defines the schema for each variant.

Is JSONL always faster or smaller?

No. Its primary benefit is independent record boundaries; actual speed and size depend on encoding, compression, buffering, and implementation.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.