Gemini's Max Output Tokens per Model
8 min read · updated August 11, 2026
Gemini publishes two numbers for every model and they are commonly read as one. The context window is how much you may send. The output token limit is how much may come back in a single response, and no amount of unused context raises it.
Two limits that are not the same limit
Google’s model reference lists an input token limit and an output token limit for each model as separate rows. They constrain different things:
- Input token limit — the size of everything you send:
contentsincluding history, the system instruction, tool declarations, and media parts. - Output token limit — the maximum
candidatesTokenCountfor one response, and the ceiling on whatmaxOutputTokensmay be set to.
A model with a one-million-token window and an eight-thousand-token output limit will read a book and will not write one. If you need 200,000 tokens of output, no single call produces it on any current Gemini model—that is a chunking problem, solved by generating sections across several calls, not by a parameter.
The documented ceilings
Two figures characterise the generations, and the jump between them is large enough to change what is designable:
Model generation Documented output token limit Gemini 1.5 Pro 8,192 Gemini 1.5 Flash 8,192 Gemini 2.0 Flash 8,192 Gemini 2.5 Pro 65,536 Gemini 2.5 Flash 65,536
The 2.5 generation raised the ceiling by a factor of eight, and it is not a coincidence that it is also the generation with thinking: the budget had to grow to accommodate reasoning tokens drawn from the same allowance. A 65,536-token ceiling with a 32,000-token thinking budget leaves roughly what an 8,192-token ceiling gave you without one.
The reliable way to find the number without reading a page is to ask the API. The models endpoint reports both limits for whatever you are about to call:
GET https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash
x-goog-api-key: $GEMINI_API_KEY
{
"name": "models/gemini-2.5-flash",
"inputTokenLimit": ...,
"outputTokenLimit": ...,
"supportedGenerationMethods": ["generateContent", "countTokens", ...]
}Reading outputTokenLimit at start-up and clamping your configured maxOutputTokens to it is four lines of code that survives every future change to the table above. It is the correct fix for a value that moves.
What happens if you do not set it
maxOutputTokens is optional. Omitted, the model’s own ceiling applies, which means the default on a 2.5 model is very large and the model will stop when it has finished rather than when it runs out of room.
That default is safe for correctness and expensive for cost control. A prompt that occasionally triggers a long answer bills for a long answer, and there is nothing in the request expressing an opinion about how long is reasonable. Setting maxOutputTokens to the length you actually expect turns an unbounded cost into a bounded one, at the price of getting MAX_TOKENS when you underestimate.
The parameter is a hard stop, not a style instruction. It does not make the model concise; it cuts it off mid-sentence. To get a short answer, ask for a short answer in the prompt and set maxOutputTokens as a safety net above the length you asked for. Using it alone as a brevity control produces truncated text, every time.
Thinking tokens come out of this budget
On thinking models, reasoning tokens are output tokens and are drawn from the same allowance before the answer is written. The response separates them:
"usageMetadata": {
"promptTokenCount": 900,
"thoughtsTokenCount": 5120,
"candidatesTokenCount": 640,
"totalTokenCount": 6660
}
Output allowance consumed = thoughtsTokenCount + candidatesTokenCount
= 5,760 tokensSo maxOutputTokens has to cover both. Set it to 1,024 on a model that will spend 1,024 tokens thinking and you get a MAX_TOKENS finish with an empty answer and a bill for the thinking—the failure traced in full on the thinking budget page.
The other ways output ends early
maxOutputTokens is one of four things that can end a generation before the model was finished, and they are easy to confuse because three of them produce short answers.
- The model finished. It emitted its end-of-turn token.
finishReasonisSTOP. A short answer here is a short answer, not a truncation, and this is the case people misdiagnose as a limit. - A stop sequence fired. A string from
generationConfig.stopSequenceswas generated, and generation halted. The finish reason is alsoSTOP, and the stop sequence itself is not included in the returned text—which is why a response can appear to end one token early for no visible reason. See the stopSequences parameter and its limits. - The output allowance ran out.
finishReason: "MAX_TOKENS". This is the only one of the four where the text is a genuine prefix of a longer answer that was going to arrive. - A filter stopped it.
SAFETY,RECITATIONand the other block values. Text may be present up to the point of the block, and it is not a prefix you can continue — asking for the rest produces the same block.
The diagnostic value of separating them is that only the third has a fix in the parameter. Raising maxOutputTokens does nothing for a stop sequence firing early, nothing for a recitation block, and nothing for a model that simply had less to say. Checking usageMetadata.candidatesTokenCount against your configured ceiling settles it in one comparison: if the count is well below the ceiling, the ceiling is not your problem.
Detecting and handling the ceiling
Hitting the limit is not an error. The call returns 200 with a partial answer and finishReason: "MAX_TOKENS". Nothing else distinguishes it from a complete response, so an application that does not read the field ships truncated text to users indefinitely without a single log line.
- Check
candidates[0].finishReasonon every response, streamed or not. Treat anything other thanSTOPas a case to handle explicitly — every value and its trigger is enumerated separately. - If it is
MAX_TOKENSand the output should have been JSON, do not attempt to parse. Truncated JSON is invalid JSON and a “repair the JSON” step will invent the missing fields. - To continue, append the partial answer to
contentsas amodelturn and send a follow-up user turn asking it to continue from where it stopped. This is a genuine continuation because the API is stateless and the partial text is now context. - If truncation is frequent rather than occasional, the fix is structural: split the task so each call produces one section. Longer ceilings postpone this; they do not remove it.