Classify text with Claude in Python: single-label, multi-label, zero-shot, and batch classification. Working code examples with structured JSON output and accuracy tips.
Claude's instruction-following ability makes it an excellent zero-shot and few-shot text classifier. This guide covers single-label, multi-label, and batch classification with structured JSON output.
pip install anthropic
import anthropic
import json
client = anthropic.Anthropic()
LABELS = ["positive", "neutral", "negative"]
def classify_sentiment(text: str) -> str:
system = f"""You are a sentiment classifier.
Return ONLY a JSON object with a single key "label".
The label must be one of: {LABELS}.
No explanation. No markdown. Raw JSON only."""
response = client.messages.create(
model="claude-haiku-4-5-20251001", # fast + cheap for classification
max_tokens=32,
temperature=0, # deterministic
system=system,
messages=[{"role": "user", "content": text}]
)
result = json.loads(response.content[0].text)
return result["label"]
print(classify_sentiment("The new API is incredibly easy to use!"))
# → "positive"
print(classify_sentiment("The package arrived yesterday."))
# → "neutral"
TOPIC_LABELS = ["billing", "technical", "account", "feature-request", "bug", "general"]
def classify_support_ticket(ticket: str) -> list[str]:
system = f"""You are a support ticket classifier.
Return ONLY a JSON object with key "labels" containing an array of applicable labels.
Labels must be from this list: {TOPIC_LABELS}.
Return an empty array if no category fits.
No explanation. Raw JSON only."""
response = client.messages.create(
model="claude-haiku-4-5-20251001",
max_tokens=64,
temperature=0,
system=system,
messages=[{"role": "user", "content": ticket}]
)
result = json.loads(response.content[0].text)
# Validate against allowed labels
return [l for l in result["labels"] if l in TOPIC_LABELS]
ticket = "I was charged twice this month and I can't log into my account."
print(classify_support_ticket(ticket))
# → ["billing", "account"]
def classify_with_examples(text: str, labels: list[str], examples: list[dict]) -> str:
"""
examples: [{"text": "...", "label": "..."}, ...]
Provide 2-5 examples per label for best accuracy.
"""
examples_str = "
".join(
f'Text: "{ex["text"]}"
Label: {ex["label"]}'
for ex in examples
)
system = f"""You are a text classifier.
Allowed labels: {labels}
Return ONLY a JSON object with key "label".
Examples:
{examples_str}"""
response = client.messages.create(
model="claude-haiku-4-5-20251001",
max_tokens=32,
temperature=0,
system=system,
messages=[{"role": "user", "content": f'Text: "{text}"
Label:'}]
)
result = json.loads(response.content[0].text)
return result["label"]
examples = [
{"text": "App crashes on launch", "label": "bug"},
{"text": "Please add dark mode", "label": "feature-request"},
{"text": "Can't reset my password", "label": "account"},
]
print(classify_with_examples("Login page freezes after update", ["bug", "feature-request", "account"], examples))
# → "bug"
def batch_classify(texts: list[str], labels: list[str]) -> str:
"""Submit up to 100K requests at 50% cost. Returns batch ID to poll."""
system = f"""You are a text classifier.
Return ONLY a JSON object with key "label".
Allowed labels: {labels}
No explanation. Raw JSON only."""
requests_list = [
{
"custom_id": f"item_{i}",
"params": {
"model": "claude-haiku-4-5-20251001",
"max_tokens": 32,
"temperature": 0,
"system": system,
"messages": [{"role": "user", "content": text}]
}
}
for i, text in enumerate(texts)
]
batch = client.beta.messages.batches.create(requests=requests_list)
print(f"Batch submitted: {batch.id} — poll until processing_status == 'ended'")
return batch.id
# batch_classify(my_texts, ["positive", "neutral", "negative"])
| Approach | Labeled data needed | Accuracy | Cost | Latency |
|---|---|---|---|---|
| Claude zero-shot | None | Good for common labels | Medium | ~1s / text |
| Claude few-shot (3-5 ex) | ~5 examples total | Better | Medium+ | ~1s / text |
| Claude Batch API | None | Same as zero-shot | 50% less | Async (minutes–hours) |
| Fine-tuned BERT | 500–5,000 per class | Best at scale | Very low | <100ms |
For bulk classification jobs, estimate your costs with the Claude API Cost Calculator. For extracting structured fields (not just labels) from text, see the structured output guide. For sentiment + summarization in one call, see the summarization guide.