Claude Has No Default max_tokens: The Ceiling by Model Version
8 min read · updated August 11, 2026
The question assumes a default that does not exist. Anthropic’s Messages API makes max_tokens a required field: omit it and the request is rejected before any tokens are generated. What has changed across versions is the maximum value the field will accept, and that has moved by more than an order of magnitude.
There is no default, because the field is required
Every call to POST /v1/messages must carry max_tokens. It sits alongside model and messages in the required set, which is a deliberate divergence from OpenAI’s Chat Completions API where the equivalent field is optional and defaults to the model’s remaining context.
The design reason is legible once you look at what the field bounds. It is a hard cap on generated output, and generated output is the expensive side of the bill and the slow side of the latency. A default of “as much as the model wants” makes an unbounded spend and an unbounded wait the thing you get by not typing anything. Requiring it makes the ceiling a decision. If you are porting code from an OpenAI-shaped client, this is the first thing that will fail, and the error is explicit about it — see the max_tokens required error.
Note also what it is not: it is not a target. The model stops when it is finished. max_tokens only decides where generation is cut off if it has not finished by then, and you find out which happened from stop_reason — "end_turn" for a natural finish versus "max_tokens" for a truncation. The full list is in what stop_reason returns.
A consequence people find counterintuitive: setting a large max_tokens costs nothing on a short answer. You are billed for tokens generated, not for tokens permitted. The reason not to set it to the ceiling on every call is not price, it is the failure modes at the edges — a runaway generation you would rather have cut short, and the streaming requirement described below, which is triggered by the budget you asked for rather than by the output you got.
The ceiling by model generation
The values below are the maximum output token counts Anthropic has documented per model in its models overview and API changelog. The direction of travel is the point: 4,096 was the whole of it for the first Claude 3 generation, and the reasoning-capable generations needed far more room because their thinking is output.
That last clause is the mechanism behind the whole table. A model that reasons before answering does so by generating tokens — the reasoning is not a separate hidden phase, it is text produced by the same autoregressive loop and drawn from the same budget. A 4,096-token ceiling is generous for an answer and nowhere near enough for an answer plus its working. The ceilings rose because the models started spending output on a new thing, not because anyone decided replies should be longer.
Claude 3 Opus / Sonnet / Haiku 4,096 Claude 3.5 Sonnet 8,192 Claude 3.5 Haiku 8,192 Claude 3.7 Sonnet 64,000 (128,000 with a beta header) Claude 4 Opus family 32,000 Claude 4 Sonnet family 64,000
The beta headers that raised it
Twice now the ceiling has been raised behind an opt-in header before becoming the default. The pattern is worth knowing because it is how Anthropic ships this class of change generally.
Claude 3.5 Sonnet launched at 4,096 and 8,192 arrived behind anthropic-beta: max-tokens-3-5-sonnet-2024-07-15, later becoming the standard behaviour with no header. Claude 3.7 Sonnet documented 64,000 as standard and 128,000 behind anthropic-beta: output-128k-2025-02-19.
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: output-128k-2025-02-19" \
-H "content-type: application/json" \
-d '{
"model": "claude-3-7-sonnet-20250219",
"max_tokens": 100000,
"messages": [{"role": "user", "content": "Write the full report."}]
}'Two things about beta headers in general. They are additive and comma separated, so you can carry more than one. And they are not permanent: the behaviour graduates and the header eventually becomes a no-op or is retired. Sending a stale one is not usually fatal, but code that depends on a beta header should be reviewed when you change model. More on the mechanism in how the anthropic-beta header works.
The two errors you will actually hit
Above the model ceiling
Sending a value above the model’s documented maximum returns a 400 invalid_request_error naming the limit. This is a per-model check, so the same request body can be valid for one model string and rejected for another — which is exactly what happens when you swap a Sonnet for an Opus and keep the 64,000.
The ten-minute streaming rule
Anthropic documents that long requests must be streamed: if max_tokens is large enough that generation could plausibly exceed about ten minutes, a non-streaming request is rejected with an error telling you to stream. The threshold is a function of the token budget and the model’s generation rate rather than a fixed number, so the practical rule is that anything asking for tens of thousands of output tokens should set stream: true.
This surprises people porting a batch job, because the job does not care about streaming and now has to consume an event stream anyway. If the work is genuinely asynchronous, the Message Batches API is the better shape for it than a long synchronous call.
Both of these are worth handling as configuration rather than as exceptions. The ceiling is a per-model constant, so the robust pattern is a lookup keyed on the model string that clamps your requested value rather than letting the API reject it — a request that would have returned a usable 32,000-token answer should not fail because a config somewhere still says 64,000. Streaming is the same shape of decision: decide it from the budget you are about to send, not from whether the caller wanted a stream.
Extended thinking spends the same budget
On models with extended thinking, max_tokens covers the thinking tokens and the visible response together. The thinking.budget_tokens value must be less than max_tokens, and what remains after the model has thought is what is available for the answer.
{
"model": "claude-3-7-sonnet-20250219",
"max_tokens": 20000,
"thinking": {"type": "enabled", "budget_tokens": 16000},
"messages": [{"role": "user", "content": "Prove it."}]
}
# 16,000 for thinking, up to 4,000 left for the answer.Size these together or you get a response that thought thoroughly and then got cut off two sentences into the answer, with stop_reason: "max_tokens" as the only evidence. The The reverse mistake is subtler and more expensive: setting max_tokens to the model ceiling and budget_tokens just below it, so that a model given a hard problem can spend tens of thousands of tokens thinking on a request that did not warrant it. The budget is a ceiling rather than a target, so this is usually harmless and occasionally very much not, and it is the kind of thing that shows up first on the bill rather than in the output. The budget interaction is covered in how budget_tokens works.