Claude Certification Guides
CCDV-F/Domain 29 min read

Lesson 2.3

Vision, PDFs and the Files API

Sending images and PDF documents to Claude as base64, URL or uploaded file references, and when the Files API saves you from re-uploading.

Claude reads images and PDFs natively through the same Messages API. There is no separate vision endpoint; you add image or document content blocks to a user message. The exam tests the three source types, the limits you must respect, and when to reach for the Files API instead of inlining bytes.

Three ways to supply a file

Every image or document block has a source whose type is one of:

source.typeFieldsUse when
base64media_type, dataThe file is local and small enough to inline
urlurlThe file is publicly fetchable
filefile_idYou uploaded it once via the Files API and reuse it

The block type must match the content: images use type: "image", PDFs and text documents use type: "document".

Images

import base64, anthropic
client = anthropic.Anthropic()

data = base64.standard_b64encode(open("chart.png", "rb").read()).decode()
resp = client.messages.create(
    model=MODEL, max_tokens=1024,
    messages=[{"role": "user", "content": [
        {"type": "image", "source": {"type": "base64",
                                     "media_type": "image/png", "data": data}},
        {"type": "text", "text": "Summarise the trend in this chart."},
    ]}],
)
const resp = await client.messages.create({
  model: MODEL, max_tokens: 1024,
  messages: [{ role: "user", content: [
    { type: "image", source: { type: "url", url: "https://example.com/chart.png" } },
    { type: "text", text: "Summarise the trend in this chart." },
  ]}],
});

Supported media types are JPEG, PNG, GIF and WebP. Put the image before the text that asks about it; that ordering produces the best results. You can send multiple images in one message and refer to them by position. Images are billed as input tokens in proportion to their pixel area, and very large images are downscaled, so resizing to roughly the longest-edge limit documented on docs.anthropic.com saves tokens without losing accuracy. Per-image size and count limits also live there.

PDFs

A PDF goes in a document block with media_type: "application/pdf". Claude extracts both the text and a rendered image of each page, which means it can read charts and scanned layouts, and it also means PDFs cost more tokens per page than plain text.

{"role": "user", "content": [
  {"type": "document",
   "source": {"type": "base64", "media_type": "application/pdf", "data": "<base64>"},
   "title": "Q3 report",
   "citations": {"enabled": true}},
  {"type": "text", "text": "What were the main risks identified?"}
]}

The base64 string must not contain newlines. Request size and page-count caps apply; check the PDF support page for the current numbers. Plain text can also be sent as a document with media_type: "text/plain" and a source.type of text, which is useful when you want citations against a text corpus.

Citations

Setting citations: {"enabled": true} on a document block makes Claude return its answer as multiple text blocks, some carrying a citations array that points back into the source: character ranges for text, page numbers for PDFs. Enable it on all documents in a request or none. Citations are incompatible with structured output formats.

The Files API

Inlining a 20 MB PDF in every request wastes bandwidth and makes requests slow. The Files API lets you upload once and reference the file by ID as many times as you like.

uploaded = client.files.upload(file=("handbook.pdf", open("handbook.pdf", "rb"),
                                     "application/pdf"))
resp = client.messages.create(
    model=MODEL, max_tokens=1024,
    messages=[{"role": "user", "content": [
        {"type": "document", "source": {"type": "file", "file_id": uploaded.id}},
        {"type": "text", "text": "List the holiday policy rules."},
    ]}],
)
import fs from "fs";
const uploaded = await client.files.upload({
  file: new File([fs.readFileSync("handbook.pdf")], "handbook.pdf",
                 { type: "application/pdf" }),
});
// then reference { type: "document", source: { type: "file", file_id: uploaded.id } }

Key behaviours: upload, list, retrieve metadata and delete are free; the file's content is billed as input tokens each time a message uses it. Files persist until deleted and are scoped to your organisation. Only files generated by server-side tools such as code execution can be downloaded; your own uploads cannot be fetched back. Per-file and per-organisation storage limits are documented on the Files page. Combine file_id references with prompt caching when the same document is queried repeatedly, because caching is what actually reduces token cost; the Files API only removes the re-upload.

Choosing a source type

  • Prototyping with a local file: base64.
  • Public asset that changes rarely: url (the API fetches it; it must be reachable without authentication).
  • The same large document across many requests, or in batches: file via the Files API.
  • Sensitive documents: avoid url from internal hosts; the fetch comes from Anthropic's servers.

Exam focus

  • Images and PDFs are sent as image and document content blocks inside a normal user message; there is no separate endpoint.
  • Three source.type values: base64, url and file (a file_id from the Files API).
  • Supported image types are JPEG, PNG, GIF and WebP; place the image before the question text.
  • PDFs are processed as text plus page images, so they cost more tokens than plain text; limits live on docs.anthropic.com.
  • The Files API removes repeated uploads but does not reduce token cost; pair it with prompt caching for that.
  • Citations are enabled per document block, apply to all or none, and cannot be combined with structured output.

Check yourself

5 questions

  1. 1.Which content block correctly supplies an image to Claude?

  2. 2.A developer uploads a company logo with media_type "image/svg+xml" and gets a 400 error. Why?

  3. 3.A developer sends a PDF as: {"type": "image", "source": {"type": "base64", "media_type": "application/pdf", "data": "..."}} and the request is rejected. Which change is correct?

  4. 4.A support tool answers 500 questions a day about the same 40-page product manual. Each request base64-encodes the 8 MB PDF and sends it inline. Which change gives the biggest improvement in upload latency and cost?

  5. 5.After calling client.files.upload(...) what does the developer use to attach the uploaded file to a message?