Without an applied server prompt POST /v1/messages, images are passed in an image block. Base64 is the most reliable option because the file is already inside the request and does not depend on an external host.
json
{
"model": "claude-opus-5",
"max_tokens": 1024,
"messages": [{
"role": "user",
"content": [
{"type": "image", "source": {
"type": "base64", "media_type": "image/jpeg", "data": "<BASE64>"
}},
{"type": "text", "text": "What's in the image?"}
]
}]
}json
{"type": "image", "source": {"type": "url", "url": "https://example.com/photo.jpg"}}- Formats: JPEG, PNG, GIF, WebP.
- Anthropic limits each image to 10 MB of base64-encoded data and 8000×8000 px. With more than 20 images, resize each side to 2000 px or less to stay within the stricter many-image limit.
- One API request allows up to 100 images with a 200k context window and up to 600 with a 1M context window; request size and token limits may stop processing sooner.
- GIF animation is not played — Claude analyzes only the first frame.
- The URL must be a direct public
https://resource with no authentication, cookies, login page, or anti-bot challenge. - The server must consistently return the correct image MIME (
image/jpeg,image/png,image/gif, orimage/webp). - Guard does not download the URL itself: the address is passed through in the Claude Messages request without a server prompt for remote retrieval.
- Anthropic's official
count_tokensmay reject a URL source even when Messages accepts the same file. For/v1/messages, Guard skips that internal count preflight and uses a safe full-context reserve; send the image as base64 when you need a preliminary exact count. - Redirects, CDN protection, hotlink protection, and temporary signed URLs may fail. Availability from an arbitrary external host is not guaranteed.
- If a URL is rejected, download the file yourself and send base64.
- Multiple images are allowed while the whole request remains under the limit.
- Images count as input tokens (depends on resolution) — see Billing.
| Family | Image input |
|---|---|
| Kimi | image_url, input_image and image blocks are accepted and passed to the model as they are; video blocks behave the same way |
| Composer | no: 400 cursor_image_input_unavailable before any charge |
| Grok | yes: inline base64, up to 16 images per request, image/png, image/jpeg, image/webp, image/gif |
json
{
"model": "cursor-grok-4.6-high",
"max_tokens": 512,
"messages": [{
"role": "user",
"content": [
{"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": "iVBORw0…"}},
{"type": "text", "text": "What is in the picture?"}
]
}]
}