You are about to hand a training file to a provider. Two things about it are invisible from the outside and expensive to get wrong.
The first is that some records are too long. They will not error. In OpenAI’s own words, “Examples longer than the default are truncated to the maximum context length, which removes tokens from the end of the training example.” The end of a chat record is the assistant’s reply — so the trainer keeps your question, cuts the answer in half, and charges you to teach the model to stop mid-sentence.
The second is which limit applies. The maximum length of one training example is not the model’s context window, and for the gpt-4.1 and gpt-4o families it is 65,536 tokens against a 128,000-token window — exactly half. A file checked against the context window looks fine and still loses the end of every long record.
role and content, so counting the raw
line overcounts; it does see the per-message framing, so counting the content alone
undercounts. On a three-message record the difference measures about 40%.
Providers bill the tokens in your file multiplied by the number of epochs. The part that is easy to get wrong is the cap: a record longer than the limit is billed at the limit, because that is all the trainer keeps. So the figure is the sum over records of the lesser of the record’s length and the limit, times the epochs — not the sum of the raw lengths. On a file with over-limit records the two differ, and epochcost shows both.
epochcost measures the file in front of it. It does not know what your provider will actually charge on the day, whether your data is any good, or whether the fine-tune will work. It never says a file is ready or safe to train on.
localStorage key holds the model you picked and a
number of epochs; your data never does. A build gate checks the shipped JavaScript for
the storage APIs it must not contain.
over-limit.jsonl contains your
actual training records — it is the most sensitive file in the set. Where it goes next is
up to you.
tokenizer.json from huggingface.co, so Hugging Face learns
which model you asked about, and your IP address. It learns nothing about your file —
the request is for a public tokenizer definition and carries none of your data. Every
OpenAI encoding is bundled, so that path makes no request at all.
feedback.benrichardson.dev. Nothing
is sent unless you open the feedback form and press Send; your files and data never are.
huggingface.co, and only if you pick an open model. Nothing else. With an
OpenAI encoding selected, epochcost works with the network switched off entirely.
epochcost answers two questions about a fine-tuning file: which records are longer than the trainer will accept, and what a pass over the file costs. It counts with the model’s own tokenizer rather than estimating from character counts, and it hands back the records you have to fix as a file you can open.
It is built and maintained by Ben Richardson. The rest of the catalogue of tools and sites lives at lab.benrichardson.dev.
Source: github.com/ben-gy/epochcost.
Its prices are still in the table because they are still correct for the organisations that can still use them. But the file this tool reads is the same file Together, Fireworks, Azure and a local trainer take, so epochcost is not built around any one provider.
tokenizer.json fetched from the Hugging Face Hub.
The sample file is generated, not collected. The conversations in it are synthetic and describe nobody.