DeepSeek-R1's Reasoning Tokens and How They're Billed
8 min read · updated August 11, 2026
A reasoning model charges you for thinking you never read. The tokens are real output tokens, they are counted in completion_tokens like any other, and on a hard prompt they can outnumber the answer several times over.
Where reasoning tokens appear
Call deepseek-reasoner and the assistant message comes back with two text fields instead of one: reasoning_content, holding the chain of thought, and content, holding the answer. The usage object does not get a matching split at the top level. There is one completion_tokens, and it covers both.
{
"id": "...",
"model": "deepseek-reasoner",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"reasoning_content": "Let me work through the constraints...",
"content": "The answer is 42."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 180,
"completion_tokens": 2114,
"total_tokens": 2294,
"prompt_cache_hit_tokens": 128,
"prompt_cache_miss_tokens": 52,
"completion_tokens_details": { "reasoning_tokens": 2050 }
}
}The breakdown lives in completion_tokens_details.reasoning_tokens. Read it as a component of completion_tokens, never as an addition to it: in the response above the answer itself is 2114 − 2050 = 64 tokens. Code that sums completion_tokens and reasoning_tokens to get a total will overstate every reasoning request, and the error grows with how hard the question was.
The two prompt_cache_* fields in the same object are DeepSeek specific and split the input side by whether the prefix was already on disk. They are covered in the page on context caching; the point here is that they partition prompt_tokens, so those two also sum to the whole rather than adding to it.
They are billed at the output rate
There is no separate reasoning tariff. Because reasoning tokens are part of completion_tokens, they are charged at whatever the output rate for the model is on DeepSeek’s pricing page, which is the rate card you should check rather than trusting any figure written down elsewhere — including here.
That simplicity has a consequence worth internalising. Output is the expensive side of the bill for every provider, because generation is memory-bandwidth bound and sequential while prefill is parallel. A reasoning model moves a large amount of work onto the expensive side by design. The cost of a reasoning request is not “a bit more than a chat request”; it is dominated by a quantity you did not specify and cannot see in advance.
A worked bill
Here is the arithmetic, with the assumptions named. Assume an output rate of $1.68 per million tokens and an uncached input rate of $0.56 per million — these are the figures DeepSeek published with its September 2025 rate change, and they are used here only as a worked example. Substitute the current numbers from the pricing page before you plan anything around this.
Assumptions (label them, they move): input, cache miss $0.56 / 1M tokens [assumed] output $1.68 / 1M tokens [assumed] requests 10,000 prompt_tokens 180 each, no cache hits reasoning_tokens 2,050 each answer tokens 64 each Input 10,000 x 180 = 1,800,000 tokens 1.8M x $0.56 / 1M = $1.008 Output (reasoning) 10,000 x 2,050 = 20,500,000 tokens 20.5M x $1.68 / 1M = $34.44 Output (answer) 10,000 x 64 = 640,000 tokens 0.64M x $1.68 / 1M = $1.0752 Total = $36.52 Share spent on text nobody reads = 34.44 / 36.52 = 94.3%
The ratio is the finding, and it is not sensitive to the assumed rate: change both prices and 94.3% barely moves, because it is set by the token counts and not by the tariff. On a prompt where the model thinks for two thousand tokens to produce a one-line answer, essentially the whole bill is the trace. That is the number to put in front of anyone asking why a reasoning model routed by default is expensive.
It also tells you where the lever is. Reducing the answer length saves nothing worth having. Deciding which requests need a reasoning model at all saves nearly everything, which is why routing simple requests to the non-reasoning endpoint is the first optimisation rather than a refinement.
They also spend your output ceiling
Reasoning tokens are counted against max_tokens, not exempt from it. Set max_tokens too low on a reasoning request and the model can spend its entire budget thinking and be cut off before it writes any answer at all: you get a response whose reasoning_content is full, whose content is empty, and whose finish_reason is length. Nothing is broken; you asked for a budget that the trace consumed.
This is why the reasoning endpoint’s documented default and maximum for max_tokens are much larger than the chat endpoint’s. Always branch on finish_reason === "length" and treat empty content with a full trace as a distinct, retryable condition rather than as a model failure.
Do not send them back
When you continue a conversation, strip reasoning_content from the assistant message before appending it to messages. DeepSeek documents this explicitly: passing the reasoning field back into a subsequent request is a 400 error, not a silent extra cost. Naive conversation code that keeps whole message objects and replays them will fail on the second turn, and the error message points at the request body rather than at the field, so it is worth knowing in advance.
# keep the answer, drop the trace, before the next turn
msg = resp.choices[0].message
messages.append({"role": "assistant", "content": msg.content})
# NOT: messages.append(msg.model_dump()) -> 400 on the next requestThe reason for the rule is that the model regenerates its trace from scratch each turn; a previous turn’s reasoning is not an input it knows how to consume. That also means each turn of a multi-turn reasoning conversation pays a fresh reasoning bill. Multi-turn is where reasoning-model spend gets away from teams, and the usage object is the only place it is visible.
Reducing the reasoning bill
Four levers, in descending order of how much they are worth.
- Send fewer requests to the reasoning model. This dominates everything else, because the difference between a reasoning request and a chat request is not a percentage — it is the difference between sixty output tokens and two thousand. Classify first, or try the cheaper model and escalate only when a validation check fails.
- Keep conversations short on the reasoning path. Each turn regenerates a full trace, so a five-turn reasoning conversation is five reasoning bills, not one amortised across five. Where the work is genuinely one hard question, ask it once with everything attached rather than building up to it.
- Set
max_tokensfrom measured percentiles. A ceiling does not reduce the typical bill — the model stops when it stops — but it bounds the tail, and the tail is where a runaway trace costs many times the median. Cap it high enough that ordinary requests are unaffected. - Make the input side cacheable anyway. Caching does nothing for reasoning tokens, which are output. It still helps if your prompts share a long prefix, and the effort is small — the caching page covers what qualifies.
What does not work is asking the model to think less. Instructions to be brief act on the answer, which is already the cheap part; the trace is generated before any instruction about output length has anything to apply to. Cost control on a reasoning model is a routing decision, not a prompting one.