Learn to use the Claude Message Batches API for cost-effective, high-throughput processing of multiple prompts. Covers setup, batch creation, monitoring, result retrieval, and troubleshooting with practical examples.
This guide covers batch processing with the Claude Message Batches API, a feature that allows you to send multiple requests to Claude in a single batch, reducing costs and improving throughput for large-scale tasks. It is intended for developers and AI practitioners who need to process high volumes of prompts efficiently, such as for data labeling, content generation, or evaluation pipelines. You will learn the core concepts, setup requirements, how to create and manage batches, interpret results, and handle errors, with practical examples and community-sourced tips.
Before you start using the Claude Message Batches API, ensure you have the following prerequisites in place:
curl, or a programming language with an HTTP client (e.g., Python with requests or httpx). The examples in this guide use curl and Python.The Claude Message Batches API allows you to group multiple individual message requests into a single batch. Each request in the batch is processed independently, but the batch is submitted and managed as a single unit. This approach offers several advantages:
A batch goes through several states during its lifecycle:
According to the official documentation, you can cancel a batch while it is in progress. Cancelled batches are not charged for any processing that has already occurred.
Each batch consists of the following components:
custom_id and a params object that mirrors the Messages API request body.custom_id and a response object containing the model's output.Before you can create batches, you need to set up your API credentials and install any necessary tools.
For this guide, we will use curl and Python. If you do not have Python installed, download it from python.org. You will also need the requests library:
pip install requests
Set your API key as an environment variable to avoid hardcoding it in scripts:
export ANTHROPIC_API_KEY="your-api-key-here"
On Windows (PowerShell):
$env:ANTHROPIC_API_KEY="your-api-key-here"

Creating a batch involves two steps: preparing the input file and submitting it to the API.
The input file must be in JSONL format. Each line is a JSON object with two required fields:
custom_id: A unique identifier for the request. This can be any string, but it must be unique within the batch. It is used to map results back to requests.params: An object containing the parameters for the Messages API request. This includes model, messages, max_tokens, and optional fields like system, temperature, stop_sequences, and metadata.Here is an example input file with two requests:
{"custom_id": "request-1", "params": {"model": "claude-3-opus-20240229", "messages": [{"role": "user", "content": "What is the capital of France?"}], "max_tokens": 100}}
{"custom_id": "request-2", "params": {"model": "claude-3-opus-20240229", "messages": [{"role": "user", "content": "Explain the theory of relativity in simple terms."}], "max_tokens": 200}}
Save this content to a file named batch_input.jsonl.
Important Notes:
custom_id must be unique within the batch. If you have duplicate IDs, the batch creation will fail.params object must be a valid Messages API request. All required fields (model, messages, max_tokens) must be present.You can submit the batch using the Batches API endpoint. The endpoint is:
POST https://api.anthropic.com/v1/messages/batches
You need to upload the input file first, then reference it in the batch creation request. The official documentation supports two methods for file upload: direct upload via multipart/form-data, or providing a URL to a publicly accessible file.
Using curl:
curl -X POST https://api.anthropic.com/v1/messages/batches \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-F "file=@batch_input.jsonl" \
-F "metadata={\"description\":\"My first batch\"}"
This command does the following:
-F "file=@batch_input.jsonl": Uploads the local file batch_input.jsonl as the batch input.-F "metadata=...": Attaches optional metadata, such as a description.The response will include the batch ID and initial status:
{
"id": "batch_abc123",
"type": "batch",
"status": "creating",
"processing_status": {
"total": 2,
"succeeded": 0,
"failed": 0,
"pending": 2
},
"request_counts": {
"total": 2,
"succeeded": 0,
"failed": 0,
"pending": 2
},
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z",
"metadata": {
"description": "My first batch"
}
}
If your input file is already hosted at a publicly accessible URL, you can submit it directly:
curl -X POST https://api.anthropic.com/v1/messages/batches \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"input_file_url": "https://example.com/batch_input.jsonl",
"metadata": {
"description": "My first batch"
}
}'
Community Tip: According to community discussions, URL-based upload is more reliable for large files because it avoids potential timeouts during the upload process. Ensure the URL is accessible from Anthropic's servers and does not require authentication.
Here is a Python script to create a batch using direct upload:
import requests
import os
api_key = os.environ["ANTHROPIC_API_KEY"]
url = "https://api.anthropic.com/v1/messages/batches"
headers = {
"x-api-key": api_key,
"anthropic-version": "2023-06-01"
}
files = {
"file": ("batch_input.jsonl", open("batch_input.jsonl", "rb"), "application/jsonl")
}
data = {
"metadata": '{"description": "My first batch"}'
}
response = requests.post(url, headers=headers, files=files, data=data)
print(response.json())
This script uploads the file and prints the batch creation response. The metadata field is passed as a string because the API expects it as a JSON-encoded string in the multipart form data.
After creating a batch, you can poll its status to know when processing is complete. The endpoint is:
GET https://api.anthropic.com/v1/messages/batches/{batch_id}
Using curl:
curl -X GET https://api.anthropic.com/v1/messages/batches/batch_abc123 \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01"
The response includes the current status and request counts:
{
"id": "batch_abc123",
"type": "batch",
"status": "in_progress",
"processing_status": {
"total": 2,
"succeeded": 1,
"failed": 0,
"pending": 1
},
"request_counts": {
"total": 2,
"succeeded": 1,
"failed": 0,
"pending": 1
},
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:05:00Z",
"metadata": {
"description": "My first batch"
}
}
Polling Strategy: The official documentation recommends polling every 30 seconds for small batches and every 60 seconds for larger batches. Avoid polling more frequently than every 10 seconds to prevent rate limiting. Use exponential backoff if you encounter rate limit errors.
import requests
import os
import time
api_key = os.environ["ANTHROPIC_API_KEY"]
batch_id = "batch_abc123"
url = f"https://api.anthropic.com/v1/messages/batches/{batch_id}"
headers = {
"x-api-key": api_key,
"anthropic-version": "2023-06-01"
}
while True:
response = requests.get(url, headers=headers)
data = response.json()
status = data["status"]
print(f"Status: {status}, Succeeded: {data['request_counts']['succeeded']}, Failed: {data['request_counts']['failed']}")
if status in ["completed", "failed", "expired", "cancelled"]:
break
time.sleep(30)
This script polls the batch status every 30 seconds until the batch reaches a terminal state.
Once the batch status is completed, you can retrieve the results. The results are stored in an output file that you can download.
The batch response includes an output_file_url field when the batch is completed. You can get this by retrieving the batch status:
curl -X GET https://api.anthropic.com/v1/messages/batches/batch_abc123 \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01"
Look for the output_file_url field in the response:
{
"id": "batch_abc123",
"status": "completed",
"output_file_url": "https://api.anthropic.com/v1/messages/batches/batch_abc123/output",
...
}
Download the output file using the URL:
curl -X GET https://api.anthropic.com/v1/messages/batches/batch_abc123/output \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-o batch_output.jsonl
The output file is in JSONL format. Each line corresponds to a request in the input file, with the same custom_id. The structure of each line is:
{
"custom_id": "request-1",
"response": {
"id": "msg_abc123",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "The capital of France is Paris."
}
],
"model": "claude-3-opus-20240229",
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 14,
"output_tokens": 8
}
}
}
If any requests in the batch failed, the batch response will include an error_file_url field. Download this file to see the errors:
curl -X GET https://api.anthropic.com/v1/messages/batches/batch_abc123/errors \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-o batch_errors.jsonl
The error file format is:
{
"custom_id": "request-3",
"error": {
"type": "invalid_request_error",
"message": "Invalid messages: content must be a string or array of content blocks."
}
}
Common error types include:
invalid_request_error: The request parameters are invalid (e.g., missing required fields, invalid message format).rate_limit_error: The request was rate limited. This can happen if your batch exceeds the rate limit for the model.server_error: An internal server error occurred. Retry the batch.authentication_error: The API key is invalid or does not have access to the model.Community Tip: According to community discussions, rate limit errors are more common with larger batches. To mitigate this, consider spreading your requests across multiple batches or using a model with higher rate limits, such as Claude 3 Haiku.
You can attach metadata to your batch when creating it. This metadata is returned in the batch status response and can be used for tracking, filtering, or organizing batches. The metadata field is a JSON object with up to 16 key-value pairs, and each value must be a string.
Example with metadata:
curl -X POST https://api.anthropic.com/v1/messages/batches \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-F "file=@batch_input.jsonl" \
-F 'metadata={"project": "data-labeling", "task": "sentiment-analysis", "batch_number": "42"}'
You can cancel a batch that is in progress. Cancelled batches are not charged for any processing that has already occurred. The endpoint is:
POST https://api.anthropic.com/v1/messages/batches/{batch_id}/cancel
Using curl:
curl -X POST https://api.anthropic.com/v1/messages/batches/batch_abc123/cancel \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01"
The response will show the batch status as cancelled.
You can list all batches associated with your account. The endpoint is:
GET https://api.anthropic.com/v1/messages/batches
Using curl:
curl -X GET "https://api.anthropic.com/v1/messages/batches?limit=20&status=completed" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01"
This endpoint supports pagination with limit (default 20, max 100) and after_id for cursor-based pagination. You can also filter by status (e.g., completed, in_progress, failed).
The params object in each request can include all the parameters supported by the Messages API, including system, temperature, top_p, stop_sequences, and metadata. Here is an example:
{"custom_id": "request-1", "params": {"model": "claude-3-opus-20240229", "messages": [{"role": "user", "content": "Translate to French: Hello, how are you?"}], "max_tokens": 100, "system": "You are a professional translator. Translate the user's text to French.", "temperature": 0.3}}
You can use different models for different requests within the same batch. This is useful for tasks that require different capabilities or cost profiles. For example:
{"custom_id": "request-1", "params": {"model": "claude-3-opus-20240229", "messages": [{"role": "user", "content": "Write a complex essay on quantum mechanics."}], "max_tokens": 1000}}
{"custom_id": "request-2", "params": {"model": "claude-3-haiku-20240307", "messages": [{"role": "user", "content": "What is 2+2?"}], "max_tokens": 50}}
Community Tip: According to community discussions, mixing models in a single batch can complicate cost tracking and rate limit management. It is often simpler to create separate batches for each model.
The optimal batch size depends on your workload and rate limits. The official documentation does not specify a maximum number of requests per batch, but the input file size limit is 100 MB. Community members report successful batches with up to 50,000 requests.
Community Recommendations:
Batch processing has higher rate limits than individual requests, but limits still apply. The exact limits depend on your account tier and the model being used. According to the official documentation, batch rate limits are typically 10x higher than individual request limits.
Community Tip: If you encounter rate limit errors, reduce the batch size or spread requests across multiple batches with a delay between submissions.
Batch processing is priced at a 50% discount. To maximize cost savings:
max_tokens to the minimum value needed for your task. Unnecessary tokens increase costs.Not all requests in a batch may succeed. The official documentation recommends:

Symptom: The batch creation request returns a 400 error.
Possible Causes and Solutions:
custom_id values are unique within the batch.params object must include model, messages, and max_tokens.Symptom: The batch status does not change from in_progress for an extended period.
Possible Causes and Solutions:
updated_at field to see if progress is being made. If updated_at is not changing, the batch may be stuck.in_progress for more than 24 hours.Community Tip: According to community discussions, batches with more than 10,000 requests can take 30-60 minutes to process. Plan your workflow accordingly.
Symptom: The batch status becomes expired.
Cause: The batch was not processed within the 24-hour time limit. This can happen if the batch is very large or if there are system issues.
Solution: Split the batch into smaller batches and resubmit. Ensure your input file is valid.
Symptom: The batch completes, but some requests have errors.
Possible Causes and Solutions:
max_tokens.Symptom: The output_file_url is not present in the batch response, or the output file contains fewer lines than expected.
Possible Causes and Solutions:
completed status for the output file to be available. Check the batch status.failed, there will be no output file. Check the error file for details.succeeded count in the batch response.Once you have mastered the basics of batch processing, explore these advanced topics:
usage information in the output file to track token consumption and costs per batch. This is useful for budgeting and optimization.Learn how to run Claude Code in CI/CD pipelines without interactive prompts. Covers authentication, permission configuration, GitHub Actions and GitLab CI integration, and troubleshooting common issues.
Learn how to install, configure, and start using Claude Code to automate desktop tasks, fix bugs, manage Git workflows, and build features directly from your terminal, IDE, or desktop app.
Complete guide to Claude Code settings, permissions, and configuration scopes. Learn how to manage user, project, local, and managed settings, use the /config command, and handle invalid entries.
Learn how to connect Claude Code to your database using the Model Context Protocol (MCP). This guide covers setup, configuration, querying, and advanced usage with real-world examples.
Learn how to set up Claude Code with GitHub Actions for automated code review, issue triage, and CI/CD workflows. Covers workflow configuration, authentication, CLI flags, and best practices.
Learn how to write Claude system prompts that produce measurably better results using hooks, settings, CLAUDE.md files, and permission rules. Covers official Anthropic patterns and community-proven techniques.
Workflows from the Neura Market marketplace related to this Claude resource