Source Intelligence
Sweep 28 Aug 2026 · 00:00Z Build v2.1.250 478 read Stable v2.1.236 Latest v2.1.250 Next v2.1.250 Feeds RSS JSON llms.txt

DisclaimerUnofficial, and not affiliated with Anthropic. Nearly all of this is read straight out of what ships: npm bundles, captured prompts, published docs. Anthropic's own notes go in verbatim, marked as theirs. The rest is my reading, and every entry carries the strings behind it. If one looks wrong, vote it down and say why.

Page history

pdf-support

build-with-claude/pdf-support

6 recorded changes 1982 lines First seen Last changed Upstream

History

build-with-claude/pdf-support Changed · +1 / -1 lines

from line 37
 
 ### 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

from line 425
 
   ```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
from line 941
   ```
 
   ```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',
from line 961
                       'type' => 'document',
                       'source' => [
                           'type' => 'file',
-                          'file_id' => $file_upload->id,
+                          'fileID' => $file_upload->id,
                       ],
                   ],
                   [
from line 1120
 
   ```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
from line 1488
 
   ```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

from line 941
   ```
 
   ```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

from line 704
 
 #### 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
from line 712
   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
from line 719
     -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",
from line 743
 
   ```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
from line 771
 
   # 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",
from line 801
   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"
     })
from line 808
   });
 
   // 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",
from line 835
   ```
 
   ```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
       {
from line 849
   });
 
   // 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?"),
               },
           },
       ],
from line 883
   }
   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 {
from line 891
   }
 
   // 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?"),
   		),
   	},
   })
from line 915
 
   // Upload the PDF file
   FileMetadata file = client
-    .beta()
     .files()
     .upload(FileUploadParams.builder().file(Path.of("/path/to/document.pdf")).build());
 
from line 921
   // 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()
         )
from line 936
     )
     .build();
 
-  BetaMessage message = client.beta().messages().create(params);
+  Message message = client.messages().create(params);
   System.out.println(message.content());
   ```
 
from line 983
 
   # 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

from line 704
 
 #### 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.