Claude can locate and label regions of an image (for example, returning bounding boxes for tables, form fields, chart elements, or UI components). This guide covers how Claude resizes images before processing them and how to work with the pixel coordinates it returns, so that boxes and points line up with your original image.
You'll need this for OCR pipelines, form extraction, chart parsing, UI element location, and any task where you act on a specific region of an image. For sending images, supported formats, and per-model resolution limits, see Vision.
Claude works best with absolute pixel coordinates. Ask for them explicitly in your prompt. For example: "Return the bounding box of each table as [x1, y1, x2, y2] (top-left and bottom-right corners) in pixel coordinates." Claude does not work well when you ask for normalized coordinates, for example: "Return bounding box coordinates between 0 and 1000." Always ask for pixel coordinates and normalize in your own code if you need to. To get coordinates as machine-readable JSON instead of prose, define a schema with structured outputs, for example an object with an [x1, y1, x2, y2] array per detected element.
Coordinates follow the standard image convention: the origin (0, 0) is the top-left corner of the image, with x increasing to the right and y increasing downward. The coordinates Claude returns are pixel positions in the image Claude sees: your image after Claude resizes it to fit the model's native resolution (see How Claude resizes and pads images). To get coordinates you can use directly, either pre-resize your image so the coordinates map one-to-one onto the image you have (see Resize your image before uploading), or rescale the coordinates Claude returns (see Rescale coordinates when you cannot pre-resize).
Claude's spatial reasoning has limits (see Limitations). Coordinate accuracy is best when you state the expected coordinate format in your prompt and spot-check results visually before processing at scale. Small elements lose precision when an image is downscaled: for fine targets, crop the region of interest and send the crop (offset returned coordinates by the crop origin), or use a high-resolution-tier model. For PDF support, pages are rasterized to images server-side at dimensions you don't control, so the returned coordinates can't be reliably mapped back onto the page. To work with coordinates on PDF content, rasterize the pages to images yourself and use the pre-resize approach.
Claude finds the largest aspect-preserving size that satisfies both of the model's image limits:
⌈width / 28⌉ × ⌈height / 28⌉ does not exceed the model's visual token budget (1568 tokens on the standard tier, 4784 on the high-resolution tier).See Resolution and token cost for which models are in which tier.
For nearly all photos and screenshots, the visual token limit is what determines the final size. The edge limit takes over only for elongated images such as panoramas or tall phone screenshots. Compute the size with the reference implementation rather than scaling to the edge length by hand: a 1920×1080 screenshot resizes to 1456×819, not 1568×882, and assuming the edge limit puts every coordinate noticeably off target.
The token limit can also trigger a resize when neither side exceeds the edge limit. Overlooking this is the most common cause of misaligned coordinates. For example, an A4 page scanned at 130 DPI is 1075×1520 pixels: both sides are under 1568 px, but it costs 39 × 55 = 2145 visual tokens, so Claude resizes it to 924×1307.
This example assumes a model on the standard resolution tier. A high-resolution-tier model doesn't resize the same scan: 2145 tokens is within its 4784-token budget, so the coordinates it returns map directly onto the 1075×1520 original. Model tiers are listed in Resolution and token cost.
Claude then pads every image, resized or not, up to the next multiple of 28 pixels on the bottom and right edges (924×1307 becomes 924×1316 in the example). The padding contains no content: Claude perceives the padded image, but the page content only ever occupies the un-padded resized region. Always normalize or rescale by the resized dimensions, not the padded dimensions; dividing by the padded dimensions scales every coordinate by a small amount.
The most reliable approach is to resize your image yourself before uploading, so the image you have is exactly the image Claude sees and the coordinates Claude returns need no conversion.
First check which resolution tier your model is on (see Resolution and token cost) and pass the matching edge and token limits. The following reference implementation computes the exact size Claude resizes an image to:
import math
def count_image_tokens(width: int, height: int) -> int:
"""Visual tokens consumed by an image: one token per 28x28 pixel patch."""
return math.ceil(width / 28) * math.ceil(height / 28)
def resized_size(
width: int,
height: int,
max_edge: int = 1568,
max_tokens: int = 1568,
) -> tuple[int, int]:
"""The size Claude resizes an image to before padding.
Defaults are for the standard resolution tier. For high-resolution-tier
models, use max_edge=2576 and max_tokens=4784. Returns (width, height).
Images that already fit within the limits are returned unchanged.
"""
def fits(w: int, h: int) -> bool:
return (
math.ceil(w / 28) * 28 <= max_edge
and math.ceil(h / 28) * 28 <= max_edge
and count_image_tokens(w, h) <= max_tokens
)
if fits(width, height):
return (width, height)
if height > width:
resized_h, resized_w = resized_size(height, width, max_edge, max_tokens)
return (resized_w, resized_h)
# Binary search along the long edge for the largest aspect-preserving
# size that fits.
aspect_ratio = width / height
lo, hi = 1, width # lo always fits; hi never fits
while lo + 1 < hi:
mid = (lo + hi) // 2
if fits(mid, max(round(mid / aspect_ratio), 1)):
lo = mid
else:
hi = mid
return (lo, max(round(lo / aspect_ratio), 1))
# The A4 example from "How Claude resizes and pads images":
print(resized_size(1075, 1520)) # (924, 1307)
# To apply the resize, use your image library, for example Pillow:
# image.resize(resized_size(*image.size))[x, y] in pixel coordinates."The Token counting endpoint estimates an image's token cost from its dimensions without fully processing it, so a successful count doesn't mean the image is within the Messages API's request limits. An image can count successfully and still be rejected when you send it.
If you cannot pre-resize (for example, when the image comes from an upstream system you can't modify), use the resize helper from Resize your image before uploading to recover the dimensions Claude saw, then map the coordinates Claude returns into normalized coordinates or back onto your original image. Claude resizes oversized images rather than rejecting them, up to the API's request limits. Beyond those limits the request fails with a validation error instead. Pass the tier limits that match the model you called: the wrong tier's limits recover the wrong resized dimensions and silently shift every coordinate. This approach requires knowing the pixel dimensions of the image you uploaded, so it does not apply to PDF uploads.
# This helper calls resized_size from the resize example on this page.
def to_relative_coordinates(
x: float,
y: float,
original_width: int,
original_height: int,
max_edge: int = 1568,
max_tokens: int = 1568,
) -> tuple[float, float]:
"""Map a pixel coordinate returned by Claude to relative coordinates in [0, 1].
Pass the dimensions of the image you uploaded. For high-resolution-tier
models, use max_edge=2576 and max_tokens=4784.
"""
resized_w, resized_h = resized_size(
original_width, original_height, max_edge, max_tokens
)
return (x / resized_w, y / resized_h)
# A table corner Claude returns at (462, 653.5) on the resized A4 page maps
# back onto the 1075x1520 original like this:
rel_x, rel_y = to_relative_coordinates(462, 653.5, 1075, 1520)
print((rel_x * 1075, rel_y * 1520)) # (537.5, 760.0)Padding is applied only to the bottom and right edges, so the origin doesn't shift and a per-axis linear rescale is sufficient. Clamp returned coordinates to the resized dimensions before rescaling, so a point slightly outside the image can't map outside your original.
The relative coordinates multiply against whatever surface you act on: the original image, a full-resolution scan, or a screen. When you act on a screen and screenshot pixels differ from logical coordinates (HiDPI displays), also divide by the display scale factor. The Computer use tool's scaling guidance covers that pattern.
Agent Skills are modular capabilities that extend Claude's functionality. Each Skill packages instructions, metadata, and optional resources (scripts, templates) that Claude uses automatically when relevant.
Give Claude screenshot, mouse, and keyboard control of a desktop environment with the computer use tool.
Process PDFs with Claude. Extract text, analyze charts, and understand visual content from your documents.
Count the tokens in a message before you send it to Claude. Use token counts to manage rate limits and costs, make model routing decisions, and fit prompts to a target length.
Was this page helpful?