[BUG] Read: Haiku 4.5 returns screenshot coordinates ~0.76x too small; the API shrinks the image again and the scale note doesn't cover it
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
When Haiku 4.5 reads a screenshot through the Read tool and is asked where something is, it answers in the coordinates of a smaller image than Claude Code says it sent. Every point comes back at about 0.76x on a 1920x1080 image and about 0.73x on a 2560x1440 one. Sonnet 5.5 answers in the image's own pixels on the same images, and Haiku is also exact on a 1280x720 image.
This is what Read tells the model, from --output-format stream-json:
- 1920x1080:
displayWidth: 1920, displayHeight: 1080, with no scale note. Claude Code treats it as sent 1:1. - 2560x1440:
displayWidth: 2000, displayHeight: 1125, plus[Image: original 2560x1440, displayed at 2000x1125. Multiply coordinates by 1.28 to map to original image.]
Haiku's answers fit an image about 1456 px wide in both cases:
- 1920x1080: 1456 / 1920 = 0.758. Haiku measured 0.762 in x and 0.756 in y.
- 2560x1440: 1456 / 2000 x 1.28 = 0.728. Haiku measured 0.731 and 0.729. It does apply the 1.28 note, but to coordinates that were already 0.728x too small.
This matches the vision docs:
- Haiku 4.5 is on the Standard resolution tier: a 1568 px long edge and 1568 visual tokens. The docs' own table lists 1920x1080 → 1456x819.
- Claude 4.7 and later models are on the High-resolution tier, up to 2576 px. That's why Sonnet 5.5 isn't affected.
- The docs say Claude returns pixel coordinates "relative to the image it sees after resizing".
Read's 2000 px cap and its "multiply by" note assume the high-resolution tier. For a Standard-tier model, the API shrinks the image a second time. Haiku answers in that smaller image's pixels, and Read's note doesn't account for the second resize.
The result is that a Haiku subagent doing anything click-shaped (computer use, GUI testing, "where is X in this screenshot") misses by hundreds of pixels on any screenshot over the Standard-tier limit. That includes every 1080p screen. The same should apply to every other Standard-tier model selectable in Claude Code. We only tested Haiku 4.5.
What Should Happen?
The coordinates Haiku gives should map back to the original image, the same way they already do for Sonnet and Opus. Either of these would do it:
- Resize to the model's own tier. For a Standard-tier model, Read resizes with the API's rule (1568 px long edge, 1568 visual tokens; the docs give a reference implementation) and puts the matching scale in its note. For example:
original 1920x1080, displayed at 1456x819. Multiply coordinates by 1.3187. The image then reaches the model unchanged, and the existing note covers the rest. In our tests Haiku is accurate on images under the limit (see Additional Information). - At least tell the model. Put the size the model will actually see in the note, not the size Claude Code sent.
The docs' "oversized_image": "error" option would also expose the mismatch as an error instead of a silent second resize.
Error Messages/Logs
No error. Haiku's answers vs the truth (dots drawn at known centres; dot radius 16-21 px):
model image x-ratio y-ratio median off max off on the dot
haiku-4-5-20251001 1280x720 1.005 0.995 3.2 px 7.6 px 8/8
haiku-4-5-20251001 1920x1080 0.762 0.756 268.8 px 471.8 px 0/8
haiku-4-5-20251001 2560x1440 0.731 0.729 405.2 px 694.3 px 0/8
sonnet-5-5 1280x720 1.000 1.000 0.0 px 0.0 px 8/8
sonnet-5-5 1920x1080 1.000 1.000 0.0 px 1.0 px 8/8
sonnet-5-5 2560x1440 1.000 1.001 1.0 px 1.0 px 8/8
Haiku, 1920x1080 (truth in brackets):
A 150,95 (192,130) B 1235,120 (1632,162) C 730,410 (960,540) D 300,655 (384,864)
E 1320,735 (1728,972) F 510,245 (672,324) G 1020,535 (1344,702) H 880,80 (1152,108)
Steps to Reproduce
- Save this script as
make_targets.py. It needs Pillow. It draws eight labelled red dots at known positions and writes the true centres next to the image:
``python``
# Usage: python3 make_targets.py 1920 1080 out.png
import sys, json
from PIL import Image, ImageDraw, ImageFont
W, H, out = int(sys.argv[1]), int(sys.argv[2]), sys.argv[3]
fracs = {"A": (0.10, 0.12), "B": (0.85, 0.15), "C": (0.50, 0.50), "D": (0.20, 0.80),
"E": (0.90, 0.90), "F": (0.35, 0.30), "G": (0.70, 0.65), "H": (0.60, 0.10)}
img = Image.new("RGB", (W, H), "white")
d = ImageDraw.Draw(img)
r = max(14, W // 120)
font = ImageFont.load_default(size=r * 2)
truth = {}
for k, (fx, fy) in fracs.items():
x, y = round(fx * W), round(fy * H)
truth[k] = [x, y]
d.ellipse([x - r, y - r, x + r, y + r], fill="red")
d.text((x + r + 6, y), k, fill="black", font=font, anchor="lm")
img.save(out)
json.dump(truth, open(out + ".truth.json", "w"))
print(out, truth)
- Make the images:
``bash``
python3 make_targets.py 1920 1080 targets-1920x1080.png
python3 make_targets.py 2560 1440 targets-2560x1440.png
python3 make_targets.py 1280 720 targets-1280x720.png
- Ask Haiku for the dots' centres, once per image:
``bash``
img=$PWD/targets-1920x1080.png
claude -p "Read the image $img with the Read tool. It has red dots labelled A to H. For each dot, give the pixel coordinates of its centre in the image's own pixels (x from the left edge, y from the top). Reply with only a JSON object like {\"A\":[x,y],...}, nothing else." \
--model claude-haiku-4-5-20251001 --allowedTools Read --output-format stream-json --verbose < /dev/null
- Compare the answer with
targets-1920x1080.png.truth.json. Every coordinate comes back at about 0.76x the truth. On the 2560x1440 image it's about 0.73x, and on 1280x720 it's correct. - Run the same command with
--model claude-sonnet-5-5. It's correct on all three images.
Claude Model
Other
Haiku 4.5 (claude-haiku-4-5-20251001). Sonnet 5.5 was the control.
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.294 (Claude Code)
Platform
Anthropic API
Operating System
Other Linux
Terminal/Shell
Non-interactive/CI environment
Additional Information
We first hit this with real desktop screenshots, not the synthetic dots above: 12 screenshots (1920x1080, 2560x1440 and 3840x2160) with 112 hand-checked click targets (launcher entries, toolbar icons, toggles, table cells), all answered through Read on 2.1.292.
| Haiku 4.5, condition | Targets hit |
|---|---|
| Full-size screenshot | 0/112 (median 347 px off; predicted/true = 0.758 in x and y) |
| Same, with a pixel ruler labelled in screen pixels drawn on the image | 2% (Haiku ignores the labels) |
| Screenshot scaled to 1280 wide first, answer in its pixels | 62% |
| Screenshot scaled to 1456x819 first | 67% (95-97% on large targets) |
Opus 5.5 and Sonnet 5.5 hit 100% and 99% of the same 112 targets on the full-size screenshots, so the targets aren't the problem. Once the image is under the API limit, Haiku's remaining misses are small targets, which is a model-skill question rather than this bug.