Claude API Stop Sequences: A Usage Example Guide
What stop sequences do in the Claude API
Stop sequences are strings you pass in your API request that tell Claude to halt generation the moment it produces that exact text. Instead of waiting for the model to naturally finish its response, you can force it to stop at a specific marker — a newline, a custom token like "END", a closing tag, or whatever fits your use case. This gives you precise control over where a response ends without relying on prompt engineering alone.
The most common reasons developers reach for stop sequences: preventing Claude from rambling past the answer you need, enforcing structured output boundaries (like stopping before a model starts a new turn in a simulated dialogue), truncating generation when a delimiter appears, and saving tokens by cutting off output as soon as the useful part is done. Below are concrete, working examples of how to use them with the stop_sequences parameter.
Basic usage example
The stop_sequences field accepts an array of strings. The API checks the generated text against each string, and the moment one matches, generation stops — the matched sequence itself is not included in the output.
curl https://api.anthropic.com/v1/messages \
-H "content-type: application/json" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "claude-3-5-sonnet-20241022",
"max_tokens": 300,
"stop_sequences": ["\n\nHuman:"],
"messages": [
{"role": "user", "content": "Write a short product description for a reusable water bottle."}
]
}'
Here, "\n\nHuman:" is a classic stop sequence pattern from multi-turn simulations — it stops Claude before it starts writing a fake continuation of the conversation as if it were the user.
Using stop sequences for structured output
A very practical pattern is stopping generation right after a delimiter you control. Say you want Claude to generate a single JSON object and nothing else:
{
"model": "claude-3-5-sonnet-20241022",
"max_tokens": 500,
"stop_sequences": ["```"],
"messages": [
{
"role": "user",
"content": "Return a JSON object with keys 'title' and 'summary' for this article, wrapped in a code block starting with ```json"
}
]
}
If you instruct the model to open a code block but then stop at the closing triple backtick, you get clean output without trailing explanation text that often follows code blocks ("Let me know if you'd like changes!").
Stopping at custom delimiters
You're not limited to natural language markers. Any string works, including ones you invent specifically for your pipeline:
const response = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": process.env.ANTHROPIC_API_KEY,
"anthropic-version": "2023-06-01"
},
body: JSON.stringify({
model: "claude-3-5-sonnet-20241022",
max_tokens: 200,
stop_sequences: ["<<END>>"],
messages: [
{
role: "user",
content: "Summarize this in one sentence and end your response with <<END>>:\n\nThe quick brown fox jumps over the lazy dog repeatedly throughout the afternoon."
}
]
})
});
const data = await response.json();
console.log(data.content[0].text);
console.log(data.stop_reason); // "stop_sequence"
Notice stop_reason in the response — when a stop sequence triggers the halt, this field returns "stop_sequence" instead of "end_turn" or "max_tokens". Checking this value in your code lets you distinguish "Claude finished naturally" from "Claude hit a stop sequence" from "Claude ran out of tokens," which matters if you're deciding whether to retry or continue a generation.
Multiple stop sequences at once
You can pass several candidates, and Claude stops at whichever one appears first:
{
"model": "claude-3-5-sonnet-20241022",
"max_tokens": 400,
"stop_sequences": ["\n\n", "###", "END_OF_ANSWER"],
"messages": [
{"role": "user", "content": "List three tips for better sleep, then stop."}
]
}
This is useful when you don't know in advance exactly which delimiter the model will use, or when you're handling output from several different prompt templates that each use a different marker.
Common pitfalls
A few things trip people up when first using stop sequences:
- Case and whitespace matter.
"END"and"end"are different strings, and"END "(with a trailing space) won't match plain"END". Match the exact casing and spacing you expect Claude to produce. - The stop sequence is stripped from output. If you need the delimiter in your final result (e.g., to split on it later), you'll need to re-add it yourself or use a different approach like structured output parsing.
- It's not a safety filter. Stop sequences control where generation ends, not what Claude is allowed to say before that point. Don't rely on them for content moderation.
- Combine with
max_tokensas a backstop. If Claude never produces your stop sequence (because it misunderstood the prompt), generation will still run untilmax_tokensis hit. Always set a sane token ceiling alongside stop sequences.
Using stop sequences through SubToAPI
If you're already calling Claude through SubToAPI — which turns your existing Claude access into a standard HTTPS API with application keys (sub_live_...) — the same stop_sequences parameter works exactly as shown above against https://api.subtoapi.app/v1/messages, just swap the header to Authorization: Bearer $SUBTOAPI_KEY. This is handy for teams who want the same request/response shape across multiple internal apps without each one managing its own provider credentials. See the messages docs for the full parameter reference, or the quickstart if you're setting this up for the first time. Streaming responses also respect stop sequences — check the streaming docs for how stop_reason surfaces in streamed events.
questions
Does the stop sequence text appear in the response? No. When Claude's output matches a stop sequence, generation halts immediately and the matched string itself is excluded from the returned content. If you need it in your final output, append it yourself after receiving the response.
Can I use regular expressions as stop sequences? No, stop_sequences only accepts literal exact-match strings, not regex patterns. If you need more flexible matching logic, you'll need to post-process the output after generation completes.
How do I know if a stop sequence actually triggered? Check the stop_reason field in the API response. It returns "stop_sequence" when a match occurred, versus "end_turn" for natural completion or "max_tokens" when the token limit was hit first.