Skip to content
{}

JSONL Viewer

Open a .jsonl or .ndjson file, read every record, and keep going past the lines that fail to parse.

0 chars | 1 lines
0 chars | 0 lines

Conversion payloads stay in this browser tab and are never placed in page URLs - see how local processing works. Privacy-safe analytics record only the tool, outcome, and a coarse input-size bucket.

How to open a JSONL file

Drag a .jsonl, .ndjson, or .log file onto the panel, or use Open file. The file is read locally and every line is parsed independently. You get a record count, a failed-line count, a blank-line count, the largest record size, and a field profile — then filter by text, by field presence, by exact field value, or to failed lines only, and click any line to expand it.

Why logs and model output use JSON Lines

A JSON array has to be closed to be valid, so an append-only writer cannot produce one incrementally without rewriting the tail on every write. JSON Lines has no closing bracket: appending a record is appending a line. That makes it the default for application logs, OpenAI and Anthropic batch files, BigQuery and Snowflake loads, Kafka dumps, and any pipeline where a process might be killed mid-write. It also means a reader can stream the file and process record N without having parsed record N+1, which is what lets a 40GB file be processed on a laptop.

What goes wrong with JSONL files

Four faults account for nearly all of them. A pretty-printed JSON object spread across several lines is not JSON Lines — each record must be on exactly one physical line. A trailing partial record from a killed writer produces one failed line at the end, which is expected and safe to drop. CRLF line endings are fine, but a lone CR is not treated as a separator by most readers. And a file that is actually a JSON array with one element per line will fail on every line because of the leading bracket and trailing commas; convert that with the JSONL to JSON tool in reverse.

InputOutputNote
{"a":1}\n{"a":2}2 recordsCorrect: one complete value per line.
{\n "a": 1\n}3 failed linesPretty-printed JSON is not JSON Lines.
[{"a":1},\n{"a":2}]2 failed linesThat is a JSON array — use JSONL to JSON in reverse.
{"a":1}\n{"a":1 record, 1 failed lineTruncated final write. Normal in live log files.

Reading JSONL in code

Every language reads the format the same way: iterate lines, parse each one, and decide what to do with the failures rather than letting them abort the run.

Python

import json

with open("events.jsonl") as handle:
    for number, line in enumerate(handle, 1):
        line = line.strip()
        if not line:
            continue
        try:
            record = json.loads(line)
        except json.JSONDecodeError as error:
            print(f"line {number}: {error}")
            continue
        process(record)

Node.js

import { createReadStream } from "node:fs";
import { createInterface } from "node:readline";

const lines = createInterface({ input: createReadStream("events.jsonl"), crlfDelay: Infinity });
let number = 0;
for await (const line of lines) {
  number += 1;
  if (!line.trim()) continue;
  try {
    process(JSON.parse(line));
  } catch (error) {
    console.error(`line ${number}: ${error.message}`);
  }
}

jq (CLI)

# Count records and show the distinct values of one field
jq -s length events.jsonl
jq -r ".level" events.jsonl | sort | uniq -c

Frequently Asked Questions

What is the difference between JSONL, NDJSON, and JSON Lines?

They are three names for the same convention: one complete JSON value per line, separated by \n, with no enclosing array and no commas between records. NDJSON is the older name, JSON Lines (jsonlines.org) is the more common one now, and .jsonl and .ndjson are both used as extensions. Nothing about the parsing differs.

Why does one bad line not break the whole file?

Because each line is parsed on its own. That is the entire point of the format: a truncated write at the end of a log file costs you the last record instead of the file. This viewer reports each failure with its line number and the parser's message, and carries on with the rest.

How large a file can this open?

The file is read into browser memory, so the practical ceiling is the tab's memory rather than a fixed number — a few hundred megabytes on a desktop browser. The record list is capped at 50,000 entries to keep the interface usable; the counts and field profile are still computed across everything that was read.

Can I turn JSONL into a normal JSON array?

Yes. "Download as JSON array" wraps every record that parsed into a single array. Lines that failed are excluded and stay listed with their line numbers so you can fix them at source rather than silently losing them.

What does the field profile tell me?

It lists every key seen across records, the percentage of records that carry it, and every JSON type that key has taken. A field at 62% coverage or one showing both string and number is usually the reason a downstream consumer is failing intermittently.

Is my data uploaded anywhere?

No. The conversion runs in JavaScript inside the page you already downloaded. There is no upload endpoint on this site, nothing is written into the URL, and closing the tab discards everything. Analytics record the tool name, whether the run succeeded, and a coarse size bucket — never the content.

Related Tools