You ask Claude Computer Use to fill a form, click submit, and read the confirmation. Claude clicks the submit button. Nothing visibly changes. Claude takes another screenshot, notices the form is still open, clicks submit again. And again. Five, ten, twenty iterations later the run is still going and your transcript is a wall of “I will click the Submit button” lines. The model is not stupid — it is reacting to what it sees, and what it sees is a UI state that did not change between turns. The loop almost always traces back to one of five things: a screenshot that captured the wrong frame, a focus state Claude cannot detect, a confirmation dialog rendered offscreen, coordinate drift after a viewport resize, or the page genuinely doing nothing because the click landed on a disabled / wrong-z-index element.
Common causes
Ordered by likelihood for typical Computer Use loops.
1. Click landed on a covering element (modal backdrop, tooltip, overlay)
Computer Use clicks at pixel coordinates. If a tooltip, modal backdrop, or pointer-events: auto overlay sits on top of the target button at click time, the click hits the overlay and the button never fires. The next screenshot looks identical, so Claude tries again.
How to spot it: Open the page manually, hover near the button, and check DevTools “Inspect” at those coordinates. If anything other than the button is the top element, that is the culprit.
2. Button is technically enabled but waiting on async validation
Many forms show the submit button as visually enabled but block the click handler until a debounced validation finishes. Claude’s click fires too early, gets silently swallowed, and the page stays put.
How to spot it: Manually click the button immediately after typing — if nothing happens for 500-1500ms then it works, this is your case.
3. Screenshot taken before the DOM settled
Claude’s screenshot tool fires after a fixed delay (often 800-1500ms). If the page does a full client-side route change with a spinner that takes 2s, Claude screenshots the spinner state and concludes “still loading, click again” — even though a click during loading is now wrong.
How to spot it: The screenshot transcript shows a spinner / skeleton at the position where content should be, and Claude keeps clicking the now-stale CTA.
4. Coordinate drift after a viewport / zoom change
If the browser zoom level, devicePixelRatio, or window size changed between turns (auto-resize, sidebar collapse, virtual keyboard on mobile emulation), the pixel coordinates Claude computed earlier no longer point at the same DOM element.
How to spot it: Compare two consecutive screenshots — if the button moved by more than a few px between turns but Claude is clicking the old position, this is it.
5. Confirmation dialog rendered offscreen or in a portal Claude does not see
Some UIs portal their modals to document.body at a position that Claude’s screenshot region misses (e.g. top of page when current scroll is mid-page). Claude sees an unchanged form, the modal is sitting offscreen waiting for input.
How to spot it: Scroll to top of page manually and check — if there is a modal there blocking the page, Claude needs to be told to scroll up first.
6. The page genuinely succeeded but the success indicator is too subtle
A toast that fades in 200ms then fades out 1.5s later. A green border that lasts 800ms. By the time Claude’s next screenshot fires, the success signal is gone, so Claude thinks the action failed.
How to spot it: Watch the page manually after the action — if the success indicator is visible for less than 2 seconds, Claude will likely miss it.
Before you start
- Save the entire screenshot sequence from the loop. Per-turn screenshots are the only ground truth for what Claude saw.
- Record the exact prompt that triggered the run — wording like “keep trying until you succeed” makes loops worse.
- Note whether the loop is deterministic (same site every time) or intermittent (sometimes works) — intermittent points at timing, deterministic points at structure.
Information to collect
- Per-turn screenshots from the loop (at minimum 3 consecutive iterations).
- The target site URL and the specific action Claude was asked to perform.
- Whether you are using Claude Computer Use through the API, the Console, or a desktop wrapper — each has different default screenshot delays.
- Browser zoom level, viewport size, and devicePixelRatio at run time.
- Any custom system prompt or tool-use instructions you supplied.
Step-by-step fix
Ordered by ROI. Cheapest checks first.
Step 1: Add an explicit wait-and-verify instruction to the prompt
The single highest-impact fix:
After every click, wait 3 seconds, take a screenshot, and verify the
expected change appeared. If the screenshot looks identical to before
the click, do NOT click the same element again. Instead, scroll, take
a wider screenshot, or check for an error message elsewhere on the page.
This breaks loops 1, 2, 3, and 6 most of the time, because Claude stops blindly retrying.
Step 2: Force a scroll to top before reading state
If you suspect the confirmation is rendered above the current scroll position:
Before deciding whether the action succeeded, scroll the page to the
top, wait 1 second, and take a screenshot. Modals and toasts often
render at the top of the document body.
Step 3: Switch from coordinate clicks to label-based actions where possible
Computer Use supports a click_by_label style instruction via prompting. Bias the prompt:
When clicking a button, identify it by its visible text label first,
not by its pixel coordinates. If the same coordinates fail twice, the
button has likely moved. Re-locate it by label.
This neutralizes coordinate drift after viewport changes.
Step 4: Lock the viewport size for the run
If you control the browser session, fix the viewport before starting the run:
# In your Computer Use environment startup
export COMPUTER_USE_VIEWPORT_WIDTH=1280
export COMPUTER_USE_VIEWPORT_HEIGHT=800
export COMPUTER_USE_DEVICE_PIXEL_RATIO=1
Or, in API calls, pass these explicitly in the tool config so resizes do not happen mid-run.
Step 5: Add a hard loop-breaker to your wrapper
Wrap Computer Use in code that detects identical consecutive screenshots:
import hashlib
last_hash = None
identical_count = 0
def on_screenshot(image_bytes):
global last_hash, identical_count
h = hashlib.sha256(image_bytes).hexdigest()
if h == last_hash:
identical_count += 1
if identical_count >= 3:
raise StopIteration("3 identical screenshots in a row — aborting loop")
else:
identical_count = 0
last_hash = h
If three consecutive screenshots hash identically, the run is stuck. Abort and surface to the user.
Step 6: For known sticky sites, pre-script the awkward step
Some sites (banking, legacy enterprise apps) are reliably hostile to Computer Use. For those, fall back to a deterministic Playwright / Selenium script for the click-and-wait step and only hand control to Claude for the parts that need reasoning.
Verify
- Re-run the original task with the new prompt. Confirm Claude no longer clicks the same element three times in a row.
- Check the screenshot sequence: between consecutive actions, the screenshots should be visibly different (modal opened, page changed, toast appeared).
- The total turn count for the task should drop by at least 40 percent compared to the loopy run.
Long-term prevention
- Treat every Computer Use prompt as a state machine: “click X, then verify Y appeared before doing anything else.” Make the verify step explicit.
- Bake a “do not click the same element twice without a state change” rule into your system prompt template.
- Always lock viewport and devicePixelRatio for a Computer Use session — never let the host environment auto-resize.
- For high-value sites, pre-record success-state screenshots so Claude has a reference of what “done” looks like.
- Pipe screenshots to a file system so you can replay any failed run end-to-end without re-charging the API.
Common pitfalls
- Telling Claude “try harder” or “keep trying” in the prompt — this actively encourages loops.
- Trusting the visible enabled state of a button without checking if it has an async-validation gate.
- Running Computer Use without a max-turn budget — a loop can rack up hundreds of turns and dollars.
- Assuming a captcha-blocked or rate-limited page is “just slow”; Claude will keep clicking forever.
- Not differentiating coordinate-based clicks from label-based clicks in your wrapper logs — without that distinction you cannot debug drift.
FAQ
Q: Claude clicks the right button but the page goes blank. What now?
Likely a CSP / network-block issue where the click triggered an outbound request the sandbox blocked. Check the Network tab in a manual test of the same flow — if you see a CORS or CSP error, your sandbox needs the destination domain allowlisted. See also Claude file connectors stuck in re-auth loop.
Q: Why does the loop happen on one site but not others?
Sites with heavy client-side routing, portal-rendered modals, or async validation are loop-prone. Static-HTML forms almost never loop. The fix is per-site prompting, not a global setting.
Q: Can I just raise max-turns and hope it eventually succeeds?
No. If it loops once it will loop forever — the input does not change between iterations, so Claude’s reasoning does not change either. You must either break the input pattern (scroll, wait, re-locate) or abort.
Q: Does the long-context model variant help?
A little — it helps Claude remember that it already tried this click twice. But the underlying screenshot-identity problem is not a context issue, so the gain is small. Prompt fixes win.
Related
- Claude file connectors stuck in re-auth loop
- Claude tool call stuck pending
- Claude thinking mode not triggering
- Claude inaccurate answers
Tags: #Troubleshooting #Claude #computer-use #automation #agent