Count Tokens in a JSONL Dataset (GPT, Claude, Llama)
JSONL token counter. Estimate tokens per record and total fine-tune cost across a JSONL (JSON Lines) file. Pick a model (GPT-4o, Claude, Gemini, Llama). Flags records over the context window. Browser-only.
100% client-side. No upload.
Count tokens
Per-record token counts
JSONL Token Counter
Estimate token totals and per-record token counts across a JSONL file, with a model picker and fine-tune cost estimate. Flags records that exceed the chosen model's context window before you waste a training run on them.
What is counted
The conversation, not the JSON around it. Each line is parsed, the message
contents are pulled out — messages[] for OpenAI and Anthropic records, a top-level
system, Gemini's contents[], or a prompt/completion
pair — and those are what get counted, plus the framing every provider adds per message (three
tokens each, and three to prime the reply). Braces, quotes and key names are not billed, and counting
them inflates a short chat record by a third. The summary shows what the raw-JSON count would have
been so you can see the difference; a record whose shape is not recognised falls back to it, and says
so.
How the estimate works
Real tokenizers (OpenAI's tiktoken, Anthropic's) mean shipping a couple of megabytes of
WASM to the browser. Instead the text is segmented the way a byte-pair encoder segments it: words
carry their leading space, a long word breaks into pieces of about five characters, digits break into
runs of three, runs of punctuation merge, and each CJK character is its own token. That is much
closer than dividing the character count by four, which is only right for ordinary English prose and
badly wrong for code, identifiers and numbers.
On plain English it lands on the exact tiktoken count for most sentences. On dense
punctuation it runs a little high, and on non-Latin scripts and emoji it runs low. A per-model factor
adjusts for the family — Claude's tokenizer splits somewhat more aggressively than OpenAI's. Treat
the result as an estimate good to a few per cent for budgeting, not as an invoice.
Fine-tune cost estimate
The cost row is tokens × epochs × $ per 1M. Put the current price in the
Price box and it uses that; leave it empty and it falls back to the figure below for
the selected model. Prices move, and a hard-coded number in a tool you visited once is exactly the
kind of thing that turns into a wrong budget — so check the provider's page and type it in.
- GPT-4o: $25 / 1M training tokens
- GPT-4o mini: $3 / 1M training tokens
- GPT-3.5 Turbo: $8 / 1M training tokens
For models with no published training price the row asks for one rather than inventing it.
Context-window check
Each model's per-request context window is fixed (e.g., 128k for GPT-4o, 200k for Claude). Records longer than that will fail at training or inference time. The summary flags how many records in your file exceed the limit so you can split or trim them before submitting — the JSONL Splitter won't help here (records stay intact), but the JSONL Viewer can help you find the long ones.
Tips & common pitfalls
- Estimate the message body, not the JSON wrapper. This tool counts the whole line as-is, which slightly overcounts because keys like
"role","content"aren't actually tokenized as part of the model input. For chat fine-tunes, the overcount is consistent (a few percent), so treat it as a safe upper bound. - Epochs matter for cost, not for context. Every epoch trains on the full file, so cost scales linearly with epochs. Default is 3 because that's what OpenAI's fine-tune jobs use unless you override it.
- Run after dedup. Duplicate examples pay tokens twice and hurt fine-tune quality. Use the JSONL Deduplicator first.
- Validate the structure first. If you're fine-tuning, confirm the file passes the OpenAI Fine-Tune Validator before estimating cost — invalid records get rejected without refund.
Example
Input — a small fine-tune dataset:
{"messages":[{"role":"user","content":"Hi"},{"role":"assistant","content":"Hello!"}]}
{"messages":[{"role":"user","content":"What is 2+2?"},{"role":"assistant","content":"4."}]}
At 3 epochs on GPT-4o mini, the summary will show ~50 tokens × 3 = 150 training tokens, costing fractions of a cent. Real datasets are millions of tokens; the estimate scales linearly.
Frequently asked questions
Why not use the real tokenizer?
It's a tradeoff. The real tokenizer is more accurate but adds ~2 MB of WASM to download. For budgeting fine-tunes the estimate is close enough — within a few percent on English chat data — and the tool stays instant on big files.
Does this work for inference cost (input/output token billing)?
Not directly — fine-tune training pricing and inference pricing differ. This tool focuses on training. For inference cost, multiply the input-token total by the published per-million input price for the model.
Why don't all Claude / GPT-4 Turbo entries show a price?
Anthropic doesn't publish a self-serve fine-tune price for Claude as of the date on this page; GPT-4 Turbo's fine-tune isn't generally available. Rather than make up numbers, those rows show "—".
Is my data sent to a server?
Never. Counting happens in your browser. See the privacy policy.