pdf-support
build-with-claude/pdf-support
History
build-with-claude/pdf-support Changed · +1 / -1 lines
### Supported platforms and models -All [active models](https://platform.claude.com/docs/en/about-claude/models/overview) support PDF processing. For PDF support through Amazon Bedrock's Converse API, see [Amazon Bedrock PDF support](https://platform.claude.com/docs/en/build-with-claude/pdf-support#amazon-bedrock-pdf-support). +All [active models](https://platform.claude.com/docs/en/models/overview) support PDF processing. For PDF support through Amazon Bedrock's Converse API, see [Amazon Bedrock PDF support](https://platform.claude.com/docs/en/build-with-claude/pdf-support#amazon-bedrock-pdf-support). ### Amazon Bedrock PDF support
build-with-claude/pdf-support Changed · +9 / -12 lines
```python Python import base64 - import httpx + import httpx2 # First, load and encode the PDF pdf_url = "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf" pdf_data = base64.standard_b64encode( - httpx.get(pdf_url, follow_redirects=True).content + httpx2.get(pdf_url, follow_redirects=True).content ).decode("utf-8") # Alternative: Load from a local file
``` ```php PHP - // The PHP SDK exposes the Files API under the beta namespace; field names can differ from other SDKs. - // The PHP SDK supports file_id document and image sources only through $client->beta->messages with the files beta. use Anthropic\Core\FileParam; $client = new Client(); // Upload the PDF file - $file_upload = $client->beta->files->upload( + $file_upload = $client->files->upload( file: FileParam::fromResource(fopen('/path/to/document.pdf', 'r'), contentType: 'application/pdf'), ); // Use the uploaded file in a message - $message = $client->beta->messages->create( + $message = $client->messages->create( maxTokens: 1024, - betas: ['files-api-2025-04-14'], messages: [ [ 'role' => 'user',
'type' => 'document', 'source' => [ 'type' => 'file', - 'file_id' => $file_upload->id, + 'fileID' => $file_upload->id, ], ], [
```python Python import base64 - import httpx + import httpx2 # First, load and encode the PDF pdf_url = "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf" pdf_data = base64.standard_b64encode( - httpx.get(pdf_url, follow_redirects=True).content + httpx2.get(pdf_url, follow_redirects=True).content ).decode("utf-8") # Create a message with the cached document
```python Python import base64 - import httpx + import httpx2 # First, load and encode the PDF pdf_url = "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf" pdf_data = base64.standard_b64encode( - httpx.get(pdf_url, follow_redirects=True).content + httpx2.get(pdf_url, follow_redirects=True).content ).decode("utf-8") # Create a batch of requests that use the document
build-with-claude/pdf-support Changed · +2 / -0 lines
``` ```php PHP + // The PHP SDK exposes the Files API under the beta namespace; field names can differ from other SDKs. + // The PHP SDK supports file_id document and image sources only through $client->beta->messages with the files beta. use Anthropic\Core\FileParam; $client = new Client();
build-with-claude/pdf-support Changed · +28 / -46 lines
#### Option 3: Files API -For PDFs you'll use repeatedly, or when you want to avoid encoding overhead, use the [Files API](https://platform.claude.com/docs/en/build-with-claude/files). These examples send the `anthropic-beta: files-api-2025-04-14` header, which the API accepts but doesn't require: +For PDFs you'll use repeatedly, or when you want to avoid encoding overhead, use the [Files API](https://platform.claude.com/docs/en/build-with-claude/files): <CodeGroup> ```bash cURL
FILE_ID=$(curl -sS -X POST https://api.anthropic.com/v1/files \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ - -H "anthropic-beta: files-api-2025-04-14" \ -F "[email protected]" | jq -r '.id') # Then use the returned file_id in your message
-H "content-type: application/json" \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ - -H "anthropic-beta: files-api-2025-04-14" \ -d @- <<EOF { "model": "claude-opus-5",
```bash CLI # First, upload your PDF to the Files API - FILE_ID=$(ant beta:files upload \ + FILE_ID=$(ant files upload \ --file ./document.pdf \ --transform id \ --raw-output) # Then use the returned file_id in your message - ant beta:messages create \ - --beta files-api-2025-04-14 \ + ant messages create \ --transform content \ --format yaml <<YAML model: claude-opus-5
# Upload the PDF file with open("/path/to/document.pdf", "rb") as f: - file_upload = client.beta.files.upload(file=("document.pdf", f, "application/pdf")) + file_upload = client.files.upload(file=("document.pdf", f, "application/pdf")) # Use the uploaded file in a message - message = client.beta.messages.create( + message = client.messages.create( model="claude-opus-5", max_tokens=1024, - betas=["files-api-2025-04-14"], messages=[ { "role": "user",
const anthropic = new Anthropic(); // Upload the PDF file - const fileUpload = await anthropic.beta.files.upload({ + const fileUpload = await anthropic.files.upload({ file: await toFile(fs.createReadStream("/path/to/document.pdf"), undefined, { type: "application/pdf" })
}); // Use the uploaded file in a message - const response = await anthropic.beta.messages.create({ + const response = await anthropic.messages.create({ model: "claude-opus-5", max_tokens: 1024, - betas: ["files-api-2025-04-14"], messages: [ { role: "user",
``` ```csharp C# - using Messages = Anthropic.Models.Messages; - var client = new AnthropicClient(); // Upload the PDF file - var fileUpload = await client.Beta.Files.Upload(new FileUploadParams + var fileUpload = await client.Files.Upload(new FileUploadParams { File = new BinaryContent {
}); // Use the uploaded file in a message - var message = await client.Beta.Messages.Create(new MessageCreateParams + var message = await client.Messages.Create(new MessageCreateParams { - Model = Messages::Model.ClaudeOpus5, + Model = Model.ClaudeOpus5, MaxTokens = 1024, - Betas = [AnthropicBeta.FilesApi2025_04_14], Messages = [ new() { Role = Role.User, - Content = new List<BetaContentBlockParam> + Content = new List<ContentBlockParam> { - new BetaRequestDocumentBlock + new DocumentBlockParam { - Source = new BetaFileDocumentSource { FileID = fileUpload.ID }, + Source = new FileDocumentSource { FileID = fileUpload.ID }, }, - new BetaTextBlockParam("What are the key findings in this document?"), + new TextBlockParam("What are the key findings in this document?"), }, }, ],
} defer pdfFile.Close() - fileUpload, err := client.Beta.Files.Upload(context.TODO(), anthropic.BetaFileUploadParams{ + fileUpload, err := client.Files.Upload(context.TODO(), anthropic.FileUploadParams{ File: anthropic.File(pdfFile, "document.pdf", "application/pdf"), }) if err != nil {
} // Use the uploaded file in a message - message, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{ + message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{ Model: anthropic.ModelClaudeOpus5, MaxTokens: 1024, - Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaFilesAPI2025_04_14}, - Messages: []anthropic.BetaMessageParam{ - anthropic.NewBetaUserMessage( - anthropic.NewBetaDocumentBlock(anthropic.BetaFileDocumentSourceParam{ + Messages: []anthropic.MessageParam{ + anthropic.NewUserMessage( + anthropic.NewDocumentBlock(anthropic.FileDocumentSourceParam{ FileID: fileUpload.ID, }), - anthropic.NewBetaTextBlock("What are the key findings in this document?"), + anthropic.NewTextBlock("What are the key findings in this document?"), ), }, })
// Upload the PDF file FileMetadata file = client - .beta() .files() .upload(FileUploadParams.builder().file(Path.of("/path/to/document.pdf")).build());
// Use the uploaded file in a message MessageCreateParams params = MessageCreateParams.builder() .model(Model.CLAUDE_OPUS_5) - .addBeta(AnthropicBeta.FILES_API_2025_04_14) .maxTokens(1024) - .addUserMessageOfBetaContentBlockParams( + .addUserMessageOfBlockParams( List.of( - BetaContentBlockParam.ofDocument( - BetaRequestDocumentBlock.builder() - .source( - BetaFileDocumentSource.builder() - .fileId(file.id()) - .build() - ) - .build() + ContentBlockParam.ofDocument( + DocumentBlockParam.builder().fileSource(file.id()).build() ), - BetaContentBlockParam.ofText( - BetaTextBlockParam.builder() + ContentBlockParam.ofText( + TextBlockParam.builder() .text("What are the key findings in this document?") .build() )
) .build(); - BetaMessage message = client.beta().messages().create(params); + Message message = client.messages().create(params); System.out.println(message.content()); ```
# Upload the PDF file file_upload = File.open("/path/to/document.pdf", "rb") do |f| - anthropic.beta.files.upload( + anthropic.files.upload( file: Anthropic::FilePart.new(f, filename: "document.pdf", content_type: "application/pdf") ) end # Use the uploaded file in a message - message = anthropic.beta.messages.create( + message = anthropic.messages.create( model: "claude-opus-5", max_tokens: 1024, - betas: ["files-api-2025-04-14"], messages: [ { role: "user",
build-with-claude/pdf-support Changed · +1 / -1 lines
#### Option 3: Files API -For PDFs you'll use repeatedly, or when you want to avoid encoding overhead, use the [Files API](https://platform.claude.com/docs/en/build-with-claude/files) (beta): +For PDFs you'll use repeatedly, or when you want to avoid encoding overhead, use the [Files API](https://platform.claude.com/docs/en/build-with-claude/files). These examples send the `anthropic-beta: files-api-2025-04-14` header, which the API accepts but doesn't require: <CodeGroup> ```bash cURL
build-with-claude/pdf-support First recorded · 2001 lines, first recorded
## Compatibility ## Before you begin ### Check PDF requirements ### Supported platforms and models ### Amazon Bedrock PDF support #### Document processing modes #### Key limitations #### Common issues ## Process PDFs with Claude ### Send your first PDF request #### Option 1: URL-based PDF document #### Option 2: Base64-encoded PDF document #### Option 3: Files API ### How PDF support works ### Estimate your costs ## Optimize PDF processing ### Improve performance ### Scale your implementation #### Use prompt caching #### Process document batches ## Next steps
The first capture of this source. The page was already there, and this is what it said.
---
title: PDF support
url: https://platform.claude.com/docs/en/build-with-claude/pdf-support
description: "Process PDFs with Claude: extract text, analyze charts, and understand visual content from your documents."
---
## Compatibility
- [ZDR](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention): eligible (excludes [Covered Models](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention#model-specific-data-retention-requirements))
- Platforms: Claude API, Claude Platform on AWS, Amazon Bedrock, Google Cloud, Microsoft Foundry
You can ask Claude about any text, pictures, charts, and tables in PDFs you provide. Some sample use cases:
* Analyzing financial reports and understanding charts/tables
* Extracting key information from legal documents
* Assisting with document translation
* Converting document information into structured formats
## Before you begin
### Check PDF requirements
Claude works with any standard PDF. Ensure your request size meets these requirements:
| Requirement | Limit |
| ------------------------- | -------------------------------------------------------------------------------------------------- |
| Maximum request size | 32 MB ([varies by platform](https://platform.claude.com/docs/en/api/overview#request-size-limits)) |
| Maximum pages per request | 600 (100 when the request's context window is under 1M tokens) |
| Format | Standard PDF (no passwords/encryption) |
Both limits are on the entire request payload, including any other content sent alongside PDFs. For large PDFs, consider uploading with the [Files API](https://platform.claude.com/docs/en/build-with-claude/files) and referencing by `file_id` to keep request payloads small.
<Tip>
Dense PDFs (many small-font pages, complex tables, or heavy graphics) can fill the context window before reaching the page limit. Requests with large PDFs can also fail before reaching the page limit, even when using the Files API. Try splitting the document into sections; for large files, because each page is processed as an image, downsampling embedded images can also help.
</Tip>
Because PDF support relies on Claude's vision capabilities, it is subject to the same [limitations and considerations](https://platform.claude.com/docs/en/build-with-claude/vision#limitations) as other vision tasks.
### Supported platforms and models
All [active models](https://platform.claude.com/docs/en/about-claude/models/overview) support PDF processing. For PDF support through Amazon Bedrock's Converse API, see [Amazon Bedrock PDF support](https://platform.claude.com/docs/en/build-with-claude/pdf-support#amazon-bedrock-pdf-support).
### Amazon Bedrock PDF support
When using PDF support through the Converse API, part of [Claude on Amazon Bedrock (Opus 4.6 and earlier)](https://platform.claude.com/docs/en/build-with-claude/claude-on-amazon-bedrock-legacy), there are two distinct document processing modes:
<Note>
**Important:** To access Claude's full visual PDF understanding capabilities in the Converse API, you must enable citations. Without citations enabled, the API falls back to basic text extraction only. Learn more about [working with citations](https://platform.claude.com/docs/en/build-with-claude/citations).
</Note>
#### Document processing modes
1. **Converse Document Chat** (Original mode - Text extraction only)
* Provides basic text extraction from PDFs
* Cannot analyze images, charts, or visual layouts within PDFs
* Uses approximately 1,000 tokens for a 3-page PDF
* Automatically used when citations are not enabled
2. **Claude PDF Chat** (New mode - Full visual understanding)
* Provides complete visual analysis of PDFs
* Can understand and analyze charts, graphs, images, and visual layouts
* Processes each page as both text and image for comprehensive understanding
* Uses approximately 7,000 tokens for a 3-page PDF
* **Requires citations to be enabled** in the Converse API
#### Key limitations
* **Converse API:** Visual PDF analysis requires citations to be enabled. There is currently no option to use visual analysis without citations (unlike the InvokeModel API).
* **InvokeModel API:** Provides full control over PDF processing without forced citations.
#### Common issues
If Claude isn't seeing images or charts in your PDFs when using the Converse API, you likely need to enable the citations flag. Without it, Converse falls back to basic text extraction only.
<Note>
This is a known constraint with the Converse API. For applications that require visual PDF analysis without citations, consider using the InvokeModel API instead.
</Note>
<Note>
Plain text files such as .txt, .csv, or .md can be used directly in document blocks: upload them to the Files API with MIME type `text/plain` and reference them by `file_id`. Binary formats such as .xlsx or .docx are not supported in document blocks and must be converted to text or PDF first. See [Working with other file formats](https://platform.claude.com/docs/en/build-with-claude/files#working-with-other-file-formats).
</Note>
## Process PDFs with Claude
### Send your first PDF request
Start with a simple example using the Messages API. You can provide PDFs to Claude in three ways:
1. As a URL reference to a PDF hosted online
2. As a base64-encoded PDF in `document` content blocks
3. By a `file_id` from the [Files API](https://platform.claude.com/docs/en/build-with-claude/files)
<Note>
On Amazon Bedrock and Google Cloud, only base64-encoded sources are currently available. On Microsoft Foundry, the Files API is not supported for deployments hosted on Azure.
</Note>
#### Option 1: URL-based PDF document
The simplest approach is to reference a PDF directly from a URL:
<CodeGroup>
```bash cURL
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-opus-5",
"max_tokens": 1024,
"messages": [{
"role": "user",
"content": [{
"type": "document",
"source": {
"type": "url",
"url": "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf"
}
},
{
"type": "text",
"text": "What are the key findings in this document?"
}]
}]
}'
```
```bash CLI
ant messages create --transform content --format yaml <<'YAML'
model: claude-opus-5
max_tokens: 1024
messages:
- role: user
content:
- type: document
source:
type: url
url: https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf
- type: text
text: What are the key findings in this document?
YAML
```
```python Python
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "document",
"source": {
"type": "url",
"url": "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf",
},
},
{"type": "text", "text": "What are the key findings in this document?"},
],
}
],
)
print(message.content)
```
```typescript TypeScript
const anthropic = new Anthropic();
const response = await anthropic.messages.create({
model: "claude-opus-5",
max_tokens: 1024,
messages: [
{
role: "user",
content: [
{
type: "document",
source: {
type: "url",
url: "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf"
}
},
{
type: "text",
text: "What are the key findings in this document?"
}
]
}
]
});
console.log(response);
```
```csharp C#
var client = new AnthropicClient();
// Create document block with URL
var documentParam = new DocumentBlockParam
{
Source = new UrlPdfSource
{
Url = "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf",
},
};
// Create a message with document and text content blocks
var message = await client.Messages.Create(new MessageCreateParams
{
Model = Model.ClaudeOpus5,
MaxTokens = 1024,
Messages =
[
new()
{
Role = Role.User,
Content = new List<ContentBlockParam>
{
documentParam,
new TextBlockParam("What are the key findings in this document?"),
},
},
],
});
Console.WriteLine(string.Join("\n", message.Content));
```
```go Go
client := anthropic.NewClient()
message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
Model: anthropic.ModelClaudeOpus5,
MaxTokens: 1024,
Messages: []anthropic.MessageParam{
anthropic.NewUserMessage(
anthropic.NewDocumentBlock(anthropic.URLPDFSourceParam{
URL: "https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf",
}),
anthropic.NewTextBlock("What are the key findings in this document?"),
),
},
})
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", message.Content)
```
```java Java
AnthropicClient client = AnthropicOkHttpClient.fromEnv();
// Create document block with URL
DocumentBlockParam documentParam = DocumentBlockParam.builder()
.source(
UrlPdfSource.builder()
.url(
"https://assets.anthropic.com/m/1cd9d098ac3e6467/original/Claude-3-Model-Card-October-Addendum.pdf"
)
.build()
)
.build();
// Create a message with document and text content blocks
MessageCreateParams params = MessageCreateParams.builder()
.model(Model.CLAUDE_OPUS_5)
.maxTokens(1024)
.addUserMessageOfBlockParams(
List.of(
ContentBlockParam.ofDocument(documentParam),
ContentBlockParam.ofText(
TextBlockParam.builder()
.text("What are the key findings in this document?")
.build()
)
)
)
.build();
Message message = client.messages().create(params);
System.out.println(message.content());
```
```php PHP
$client = new Client();
$message = $client->messages->create(
maxTokens: 1024,
messages: [
[
'role' => 'user',
'content' => [
[
'type' => 'document',
'source' => [
'type' => 'url',
Cut at 300 lines.