When would you choose a URL image source over base64 in Anthropic's Messages API?
answer
- who holds the bytes decides the shape
- inline always works, always repeats
- a fetch you do not control can fail
- upload once when the image repeats
- beta flag and platform gaps on the Files API
basics
~20 sChoose a URL source when the image is already hosted somewhere Anthropic can reach and you want to keep bytes out of the request body. Choose base64 for private or locally generated images, and the Files API when the same image is reused across many calls.
solid answer
~50 sThe three source shapes trade different costs. **base64** inlines the bytes, which always works — including for images your process just generated — but inflates the request by about a third and re-sends the whole payload on every call. **url** hands the fetch to Anthropic: the body stays small, but the image must be reachable from Anthropic's network over the public internet, so private buckets need pre-signed URLs, and you have imported a dependency you do not control (a dead link, an expired signature, or slow origin now shows up as request failure or latency). **file** uploads once via the Files API and references a `file_id` afterwards, which is the right answer when the same image is used across many requests or many turns; it needs the `files-api-2025-04-14` beta flag on both the upload and the message call, and the Files API is not available on Amazon Bedrock or Google Vertex AI. Portability across hosting platforms is therefore part of the decision.
code
python · 21 linesfrom anthropic import Anthropic
client = Anthropic()
uploaded = client.beta.files.upload(
file=("diagram.png", open("diagram.png", "rb"), "image/png"),
)
response = client.beta.messages.create(
model="claude-opus-5",
max_tokens=1024,
betas=["files-api-2025-04-14"],
messages=[{
"role": "user",
"content": [
{"type": "image",
"source": {"type": "file", "file_id": uploaded.id}},
{"type": "text", "text": "Which component talks to the queue?"},
],
}],
)go deeper
Know that the same image can be delivered three ways and that base64 is the one that always works because it needs nothing external to be reachable.
Compare the three shapes on payload size and repetition, and explain that a url source is fetched by Anthropic's servers rather than by your client.
Reason about failure modes end to end: unreachable or expired links, retry semantics when the fetch itself failed, file lifecycle and deletion, and the bandwidth cost of resending inlined images every turn.
Own the cross-cutting decision — what content may legally be exposed at a fetchable URL, where uploaded files are retained and expired, and whether depending on a beta surface is acceptable given the platforms you must deploy to.
## Three ways to deliver the same pixels All three source shapes end in the same place — pixels tokenised as input — so the choice is entirely operational. What differs is who holds the bytes, who pays to move them, and what can fail. ## base64: the always-works default Inlining bytes has one great virtue: no third party needs access to anything. An image your service rendered a millisecond ago, a screenshot from a headless browser, a crop you computed in memory, a frame from a private video — all of these can be encoded and sent without publishing them anywhere. For one-shot requests over images that do not already exist as URLs, this is the correct default. The costs are payload size and repetition. Encoding inflates by roughly a third, and in a multi-turn conversation the same encoded blob is re-uploaded with every request because the Messages API is stateless — you resend the whole history each turn. A long agent loop over a few screenshots can spend a surprising amount of wall-clock time simply pushing the same megabytes. ## url: small requests, borrowed risk A URL source shrinks the request body to a string and moves the transfer to Anthropic's infrastructure. If your images already live in a CDN or a public bucket, this is efficient and usually faster end to end. The catch is that the fetch must succeed from Anthropic's side, which introduces failure modes your local tests will not reproduce: a private object-storage path that works from your VPC, a pre-signed URL whose expiry is shorter than your retry window, an origin that rate-limits unfamiliar clients, a redirect chain, or a firewall that only allows your own egress ranges. There is also a data-governance dimension — the image must be exposed at a URL that anyone holding the link can retrieve, which some classes of content simply may not be. Retries deserve thought here. If a request fails after the fetch, re-sending it re-fetches; if it fails because of the fetch, retrying the same expired signed URL will fail identically forever. Signed URLs should therefore be minted with lifetimes comfortably longer than your maximum retry window, or refreshed as part of the retry. ## file: upload once, reference many times The Files API is the right shape when the same image is read repeatedly — a reference diagram every session consults, a product photo compared against many inputs, a screenshot revisited across a long agent loop. You upload once, keep the returned identifier, and every later request carries a short string instead of megabytes. The constraints are real and worth naming in an interview. It is a beta surface, so the `files-api-2025-04-14` flag must be present on both the upload call and the `messages` call that references the file. The content-block type must match the file's MIME type — an image goes in an `image` block, a PDF in a `document` block. Uploaded files persist until you delete them, which makes lifecycle management your problem: an org that uploads per request and never deletes will accumulate storage. And the Files API is not offered on Amazon Bedrock or Google Vertex AI, so code that depends on it is not portable to those platforms. ## A decision rule Ask two questions. Is this image reused? If yes, upload it and reference the `file_id`. If no, is it already published somewhere Anthropic can fetch, and is publication acceptable for this content? If yes, use a `url` source; if no, inline it as base64. Then sanity-check the failure story: for `url`, what happens when the fetch fails or the signature expires; for `file`, what deletes the file when the workflow ends; for base64, whether the repeated upload cost across turns is acceptable, and whether stale images should be pruned from history entirely once their information has been extracted.
- Your URL images live in a private S3 bucket. What has to change?Anthropic fetches server-side, so a bucket-private path is unreachable. Either pre-sign the URLs with a lifetime longer than your retry window, or stop using the url shape and inline the bytes as base64. Pre-signing is a deliberate exposure decision: anyone with the link can read the object until it expires, so short-lived signatures and narrow scopes matter.
- Which shape would you pick for a ten-turn agent loop that keeps referring to one screenshot?Upload it through the Files API and reference the file_id. Because the Messages API is stateless, an inlined base64 screenshot is re-uploaded on every one of the ten turns; a file_id sends a short string instead. The token cost of the image is unchanged — that is charged per turn regardless — but the bandwidth and latency of resending the payload disappear.
- What breaks if you move Files-API-based code onto Amazon Bedrock or Vertex AI?The Files API is not available on those platforms, so a request referencing a file_id has nowhere to resolve it. Portable code has to fall back to base64 or url sources. If multi-platform deployment is a requirement, keep the source shape behind an abstraction so switching does not mean rewriting every call site.
saying these in an interview costs you the question
- Assuming a URL source is fetched by the SDK, not by Anthropic
- Using presigned URLs shorter-lived than the retry window
- Believing a file_id makes the image tokens cheaper
- Uploading a file per request and never deleting it
- Expecting Files API code to run unchanged on Bedrock or Vertex