Reading 50MB JSONL logs with a viewer in 2026
Use a browser-based JSONL viewer that parses each line as its own JSON object and lays the results out in a filterable, sortable table. That's the fastest way to read newline-delimited logs without writing a throwaway script. Paste the file, get columns, filter to the rows you care about, export what's left. No terminal gymnastics and no 2GB file crashing your editor. Works offline because everything runs client-side.
The jsonl viewer I link to below is one I built. I got tired of it: I tried six different online JSON tools last spring and every one of them choked the moment I pasted newline-delimited data, because they all assume a single JSON document and JSONL is a stream of them. Mine runs entirely in your browser. No signup, no upload, nothing leaves your machine, and it's free. If you've got a better one, please tell me.
The log file that killed my text editor
Last Tuesday, around 2am, I was chasing a production timeout. The only evidence I had was an NDJSON log the service had been streaming to disk: 340 MB, roughly 1.2 million lines, one JSON object per line. I did the obvious thing first and opened it in my editor. It thought about that for a while. The fans spun up. Then the window went white and stopped responding. Cool.
So I fell back to jq. jq 'select(.level == "error")' app.log does work, and honestly jq is a wonderful tool, but I couldn't remember the exact field names, I kept getting the filter slightly wrong, and every failed guess re-streamed the whole file from the top. Twenty minutes in I still hadn't seen a single row. The error turned out to be on line 811,406, but I didn't know that yet. All I wanted was to see the shape of the data first, then decide what to filter. That's the gap.
JSONL (also called NDJSON or JSON Lines, same idea under different names) is a stream of JSON values with one per line. Log pipelines love it because you can append a line without rewriting the file, and a crash mid-write only costs you the last line instead of the whole document. The catch is that most JSON tooling assumes a single document, so it reads your 1.2 million lines and immediately throws on the second {.
How a JSONL viewer parses a stream of objects
The core of a JSONL viewer is almost embarrassingly small. You split on newlines and parse each non-blank line on its own. The one trick that matters is not letting a single bad line kill the whole render, so you catch per line and keep going.
// Split, drop blanks, parse each line independently.
function parseJSONL(text) {
return text
.split('\n')
.filter((line) => line.trim() !== '')
.map((line, i) => {
try {
return { ok: true, row: JSON.parse(line) };
} catch (err) {
return { ok: false, line: i + 1, raw: line, error: err.message };
}
});
}
const sample = `{"ts":"2026-04-11T02:14:03Z","level":"error","msg":"timeout","ms":9812}
{"ts":"2026-04-11T02:14:04Z","level":"info","msg":"retry","attempt":2}
not valid json
{"ts":"2026-04-11T02:14:06Z","level":"info","msg":"ok"}`;
console.log(parseJSONL(sample));
Run that and you get four results back. Three parse cleanly into row objects, and the not valid json line comes back as { ok: false, line: 3, ... } instead of blowing up the other three. A viewer takes that array, unions all the keys it sees to build columns (ts, level, msg, ms, attempt), and paints a table. Now level is a column you can filter, not a string you have to grep for.
You don't have to run this yourself. Paste your file into the .
SOCIAL SHARE CARD GENERATOR