Follow Discord
Sweep 22 Oct 2026 · 21:04Z Build v2.1.309 528 read Stable v2.1.308 Latest v2.1.308 Next v2.1.309 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · api

computer-use-tool changedagents-and-tools/tool-use/computer-use-tool

Nearest release: v2.1.238, published an hour before this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Recorded here
Lines+994added
Lines−952removed
From line 1 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits27to this page, all time

### Batch actions ### Implement the computer use tool ### Handle errors ### Size screenshots to fit image limits ### Manage screenshot history ### Diagnose click issues ### Follow implementation best practices ## Migrate from `computer_20251124` ## Earlier tool versions ## Limitations ## Overview ### Start with the reference implementation #### Implement the computer use tool #### Handle errors #### Size screenshots to fit image limits #### Diagnose click issues #### Follow implementation best practices ## Understand computer use limitations

The whole hunk

from line 1, old and new numbered
/
lines

The two sides of this change are more than 400 edits apart, too far apart to line up, so this is the differ's own diff of it and the words inside a line are not marked.

from line 1
11---
22title: Computer use tool
33url: https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool
4description: Give Claude screenshot, mouse, and keyboard control of a desktop environment with the computer use tool.
4description: Give Claude screenshot, mouse, and keyboard control of a desktop environment with the computer use tool, the computer_toolset_20260801 client toolset.
55---
66 
77## Compatibility
8- Status: Beta
9- [Beta header](https://platform.claude.com/docs/en/api/beta-headers): `computer-use-2025-11-24`
108- [ZDR](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention): eligible (excludes [Covered Models](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention#model-specific-data-retention-requirements))
11- Supported models: `claude-opus-5`, `claude-sonnet-5`, `claude-opus-4-8`, `claude-opus-4-7`, `claude-opus-4-6`, `claude-sonnet-4-6`, `claude-opus-4-5-20251101`
12- Platforms: Claude API (beta), Claude Platform on AWS (beta), Amazon Bedrock (beta), Google Cloud (beta), Microsoft Foundry (beta)
9- Supported models: `claude-fable-5`, `claude-mythos-5`, `claude-opus-5`, `claude-sonnet-5`, `claude-opus-4-8`
10- Platforms: Claude API, Claude Platform on AWS (beta), Amazon Bedrock (beta), Google Cloud (beta), Microsoft Foundry (beta)
11- Claude Opus 4.7, Claude Opus 4.6, Claude Sonnet 4.6, and Claude Opus 4.5 support computer use only through the earlier `computer_20251124` tool version, which requires a beta header; see [Earlier tool versions](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#earlier-tool-versions).
12- Platforms other than the Claude API currently offer only the [earlier beta tool versions](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#earlier-tool-versions).
1313 
1414Claude can interact with computer environments through the computer use tool, which provides screenshot capabilities and mouse/keyboard control for autonomous desktop interaction.
1515 
16The computer use tool is an Anthropic-defined [client toolset](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-reference#client-toolsets): one `{"type": "computer_toolset_20260801"}` entry in `tools` gives Claude 17 member tools such as `screenshot`, `left_click`, `type`, and `zoom`, and your application runs every call in an environment you control. It isn't currently available in [Claude Managed Agents](https://platform.claude.com/docs/en/managed-agents/tools). Claude's calls are `tool_use` blocks whose `name` is the member and which carry `"toolset_name": "computer"`, often several per turn (a [batch action](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#batch-actions)).
17 
18For tasks that stay inside webpages, the [browser use tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/browser-use-tool) is the closer fit: its member tools read and act on the page itself, and it doesn't need a full desktop environment.
19 
1620<Note>
17 On Claude Sonnet 4.5, Claude Haiku 4.5, Claude Opus 4.1 ([retired, except on Bedrock and Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)), Claude Sonnet 4 ([retired, except on Bedrock and Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)), and Claude Opus 4 ([retired, except on Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)), use the earlier `computer-use-2025-01-24` [beta header](https://platform.claude.com/docs/en/api/beta-headers) instead of `computer-use-2025-11-24`.
18 
19 Reach out through the [feedback form](https://forms.gle/H6UFuXaaLywri9hz6) to share your feedback on this feature.
21 Computer use is generally available on the Claude API as the `computer_toolset_20260801` toolset, with no beta header; see [Compatibility](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#compatibility) for the supported models.
22 
23 Existing `computer_20251124` integrations keep working, and earlier tool versions remain available in beta for models and platforms that don't support the toolset. See [Migrate from `computer_20251124`](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#migrate-from-computer-20251124) to upgrade, or [Earlier tool versions](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#earlier-tool-versions) for the beta headers.
2024</Note>
2125 
22## Overview
23 
24Computer use is a beta feature that enables Claude to interact with desktop environments. This tool provides:
25 
26* **Screenshot capture:** See what's currently displayed on screen
27* **Mouse control:** Click, drag, and move the cursor
28* **Keyboard input:** Type text and use keyboard shortcuts
29* **Desktop automation:** Interact with any application or interface
30 
31While computer use can be augmented with other tools such as bash and text editor for more comprehensive automation workflows, computer use specifically refers to the computer use tool's capability to see and control desktop environments.
32 
33For model support, see the [Tool reference](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-reference).
34 
3526## Security considerations
3627 
37Computer use is a beta feature with unique risks distinct from standard API features. These risks are heightened when interacting with the internet.
28Computer use has unique risks distinct from standard API features. These risks are heightened when interacting with the internet.
3829 
3930<Warning>
4031 To minimize risks, consider taking precautions such as:
from line 44
5344 
5445Inform end users of relevant risks and obtain their consent prior to enabling computer use in your own products.
5546 
56<Card title="Computer use reference implementation" icon="computer" href="https://github.com/anthropics/anthropic-quickstarts/tree/main/computer-use-demo">
57 Get started with the computer use reference implementation that includes a web interface, Docker container, example tool implementations, and an agent loop.
58</Card>
59 
6047## Quick start
6148 
62Here's how to get started with computer use:
49Add the computer use toolset to the `tools` array of a [Messages API](https://platform.claude.com/docs/en/api/messages/create) request as `{"type": "computer_toolset_20260801"}`. The request needs no beta header. This example also declares the [text editor tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/text-editor-tool) and [bash tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/bash-tool), which Claude typically uses alongside computer use:
6350 
6451<CodeGroup>
6552 ```bash cURL
from line 54
6754 -H "content-type: application/json" \
6855 -H "x-api-key: $ANTHROPIC_API_KEY" \
6956 -H "anthropic-version: 2023-06-01" \
70 -H "anthropic-beta: computer-use-2025-11-24" \
7157 -d '{
7258 "model": "claude-opus-5",
7359 "max_tokens": 1024,
7460 "tools": [
7561 {
76 "type": "computer_20251124",
77 "name": "computer",
78 "display_width_px": 1024,
79 "display_height_px": 768,
80 "display_number": 1
62 "type": "computer_toolset_20260801"
8163 },
8264 {
8365 "type": "text_editor_20250728",
from line 80
9880 ```
9981 
10082 ```bash CLI
101 ant beta:messages create --beta computer-use-2025-11-24 <<'YAML'
83 ant messages create <<'YAML'
10284 model: claude-opus-5
10385 max_tokens: 1024
10486 tools:
105 - type: computer_20251124
106 name: computer
107 display_width_px: 1024
108 display_height_px: 768
109 display_number: 1
87 - type: computer_toolset_20260801
11088 - type: text_editor_20250728
11189 name: str_replace_based_edit_tool
11290 - type: bash_20250124
from line 98
12098 ```python Python
12199 client = anthropic.Anthropic()
122100 
123 response = client.beta.messages.create(
124 model="claude-opus-5", # or another compatible model
101 response = client.messages.create(
102 model="claude-opus-5",
125103 max_tokens=1024,
126104 tools=[
127 {
128 "type": "computer_20251124",
129 "name": "computer",
130 "display_width_px": 1024,
131 "display_height_px": 768,
132 "display_number": 1,
133 },
105 {"type": "computer_toolset_20260801"},
134106 {"type": "text_editor_20250728", "name": "str_replace_based_edit_tool"},
135107 {"type": "bash_20250124", "name": "bash"},
136108 ],
137109 messages=[{"role": "user", "content": "Save a picture of a cat to my desktop."}],
138 betas=["computer-use-2025-11-24"],
139110 )
140111 print(response)
141112 ```
from line 114
143114 ```typescript TypeScript
144115 const client = new Anthropic();
145116 
146 const response = await client.beta.messages.create({
117 const response = await client.messages.create({
147118 model: "claude-opus-5",
148119 max_tokens: 1024,
149120 tools: [
150121 {
151 type: "computer_20251124",
152 name: "computer",
153 display_width_px: 1024,
154 display_height_px: 768,
155 display_number: 1
122 type: "computer_toolset_20260801"
156123 },
157124 {
158125 type: "text_editor_20250728",
from line 130
163130 name: "bash"
164131 }
165132 ],
166 messages: [{ role: "user", content: "Save a picture of a cat to my desktop." }],
167 betas: ["computer-use-2025-11-24"]
133 messages: [{ role: "user", content: "Save a picture of a cat to my desktop." }]
168134 });
169135 
170136 console.log(response);
171137 ```
172138 
173139 ```csharp C#
174 using Anthropic.Models.Beta.Messages;
175 using Messages = Anthropic.Models.Messages;
176 
177140 var client = new AnthropicClient();
178141 
179142 var parameters = new MessageCreateParams
180143 {
181 Model = Messages::Model.ClaudeOpus5,
144 Model = Model.ClaudeOpus5,
182145 MaxTokens = 1024,
183 Tools = new BetaToolUnion[]
184 {
185 new BetaToolComputerUse20251124
186 {
187 DisplayWidthPx = 1024,
188 DisplayHeightPx = 768,
189 DisplayNumber = 1
190 },
191 new BetaToolTextEditor20250728(),
192 new BetaToolBash20250124()
193 },
146 Tools =
147 [
148 new ComputerToolset20260801(),
149 new ToolTextEditor20250728(),
150 new ToolBash20250124(),
151 ],
194152 Messages =
195153 [
196 new BetaMessageParam
154 new MessageParam
197155 {
198156 Role = Role.User,
199 Content = "Save a picture of a cat to my desktop."
200 }
157 Content = "Save a picture of a cat to my desktop.",
158 },
201159 ],
202 Betas = ["computer-use-2025-11-24"]
203160 };
204161 
205 var response = await client.Beta.Messages.Create(parameters);
162 var response = await client.Messages.Create(parameters);
206163 Console.WriteLine(response);
207164 ```
208165 
209166 ```go Go
210167 client := anthropic.NewClient()
211168 
212 response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
169 response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
213170 Model: anthropic.ModelClaudeOpus5,
214171 MaxTokens: 1024,
215 Tools: []anthropic.BetaToolUnionParam{
216 {OfComputerUseTool20251124: &anthropic.BetaToolComputerUse20251124Param{
217 DisplayWidthPx: 1024,
218 DisplayHeightPx: 768,
219 DisplayNumber: anthropic.Int(1),
220 }},
221 {OfTextEditor20250728: &anthropic.BetaToolTextEditor20250728Param{}},
222 {OfBashTool20250124: &anthropic.BetaToolBash20250124Param{}},
172 Tools: []anthropic.ToolUnionParam{
173 {OfComputerToolset20260801: &anthropic.ComputerToolset20260801Param{}},
174 {OfTextEditor20250728: &anthropic.ToolTextEditor20250728Param{}},
175 {OfBashTool20250124: &anthropic.ToolBash20250124Param{}},
223176 },
224 Messages: []anthropic.BetaMessageParam{
225 anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Save a picture of a cat to my desktop.")),
226 },
227 Betas: []anthropic.AnthropicBeta{
228 "computer-use-2025-11-24", // no SDK exposes a named constant for this beta yet
177 Messages: []anthropic.MessageParam{
178 anthropic.NewUserMessage(anthropic.NewTextBlock("Save a picture of a cat to my desktop.")),
229179 },
230180 })
231181 if err != nil {
232182 log.Fatal(err)
233183 }
234 fmt.Println(response)
184 fmt.Println(response.RawJSON())
235185 ```
236186 
237187 ```java Java
238 import com.anthropic.models.beta.messages.BetaMessage;
239 import com.anthropic.models.beta.messages.BetaToolBash20250124;
240 import com.anthropic.models.beta.messages.BetaToolComputerUse20251124;
241 import com.anthropic.models.beta.messages.BetaToolTextEditor20250728;
242 import com.anthropic.models.beta.messages.MessageCreateParams;
243 import com.anthropic.models.messages.Model;
188 import com.anthropic.models.messages.ComputerToolset20260801;
189 // ...
190 import com.anthropic.models.messages.ToolBash20250124;
191 import com.anthropic.models.messages.ToolTextEditor20250728;
244192 
245193 void main() {
246194 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
from line 196
248196 MessageCreateParams params = MessageCreateParams.builder()
249197 .model(Model.CLAUDE_OPUS_5)
250198 .maxTokens(1024L)
251 .addTool(BetaToolComputerUse20251124.builder()
252 .displayWidthPx(1024L)
253 .displayHeightPx(768L)
254 .displayNumber(1L)
255 .build())
256 .addTool(BetaToolTextEditor20250728.builder().build())
257 .addTool(BetaToolBash20250124.builder().build())
199 .addTool(ComputerToolset20260801.builder().build())
200 .addTool(ToolTextEditor20250728.builder().build())
201 .addTool(ToolBash20250124.builder().build())
258202 .addUserMessage("Save a picture of a cat to my desktop.")
259 .addBeta("computer-use-2025-11-24")
260203 .build();
261204 
262 BetaMessage response = client.beta().messages().create(params);
205 Message response = client.messages().create(params);
263206 IO.println(response);
264207 }
265208 ```
from line 210
267210 ```php PHP
268211 $client = new Client();
269212 
270 $response = $client->beta->messages->create(
213 $response = $client->messages->create(
271214 maxTokens: 1024,
272215 messages: [
273216 ['role' => 'user', 'content' => 'Save a picture of a cat to my desktop.'],
274217 ],
275218 model: 'claude-opus-5',
276219 tools: [
277 [
278 'type' => 'computer_20251124',
279 'name' => 'computer',
280 'display_width_px' => 1024,
281 'display_height_px' => 768,
282 'display_number' => 1,
283 ],
220 ['type' => 'computer_toolset_20260801'],
284221 [
285222 'type' => 'text_editor_20250728',
286223 'name' => 'str_replace_based_edit_tool',
from line 227
290227 'name' => 'bash',
291228 ],
292229 ],
293 betas: ['computer-use-2025-11-24'],
294230 );
295231 
296232 echo $response;
from line 235
299235 ```ruby Ruby
300236 client = Anthropic::Client.new
301237 
302 response = client.beta.messages.create(
238 response = client.messages.create(
303239 model: "claude-opus-5",
304240 max_tokens: 1024,
305241 tools: [
306 {
307 type: "computer_20251124",
308 name: "computer",
309 display_width_px: 1024,
310 display_height_px: 768,
311 display_number: 1
312 },
242 { type: "computer_toolset_20260801" },
313243 {
314244 type: "text_editor_20250728",
315245 name: "str_replace_based_edit_tool"
from line 251
321251 ],
322252 messages: [
323253 { role: "user", content: "Save a picture of a cat to my desktop." }
324 ],
325 betas: ["computer-use-2025-11-24"]
254 ]
326255 )
327256 
328257 puts response
329258 ```
330259</CodeGroup>
331260 
332<Note>
333 A beta header is only required for the computer use tool.
334 
335 The preceding example shows all three tools being used together, which requires the beta header because it includes the computer use tool.
336</Note>
261When Claude acts on the desktop, the response has a `stop_reason` of `tool_use` and contains one or more member `tool_use` blocks, each naming a member tool and carrying `"toolset_name": "computer"`. Partway through this task, after Claude has seen a screenshot of the desktop, a response might look like this:
262 
263```json Output
264{
265 "id": "msg_01UZ3bXcQH8mTqNhVfL9eK2p",
266 "type": "message",
267 "role": "assistant",
268 "model": "claude-opus-5",
269 "content": [
270 {
271 "type": "text",
272 "text": "I'll open the web browser to find a picture of a cat."
273 },
274 {
275 "type": "tool_use",
276 "id": "toolu_01WkoTUvSHDzTBu2xnGk8Ep8",
277 "name": "left_click",
278 "toolset_name": "computer",
279 "input": { "coordinate": [512, 742] }
280 },
281 {
282 "type": "tool_use",
283 "id": "toolu_017nJn3RgSCkTMwuZDb4uUov",
284 "name": "screenshot",
285 "toolset_name": "computer",
286 "input": {}
287 }
288 ],
289 "stop_reason": "tool_use",
290 "stop_sequence": null
291}
292```
293 
294Your application runs each call in order in your own environment, returns one `tool_result` block per `tool_use` block, and calls the API again; [How computer use works](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#how-computer-use-works) describes that loop, and the rest of this page shows how to implement it.
337295 
338296***
339297 
from line 299
341299 
342300<Steps>
343301 <Step title="Provide Claude with the computer use tool and a user prompt" icon="tool">
344 * Add the computer use tool (and optionally other tools) to your API request.
302 * Add the computer use toolset (and optionally other tools) to the `tools` array of your API request.
345303 * Include a user prompt that requires desktop interaction, for example, "Save a picture of a cat to my desktop."
346304 </Step>
347305 
348 <Step title="Claude selects the computer use tool" icon="wrench">
349 * Claude assesses if the computer use tool can help with the user's query.
350 * If yes, Claude constructs a properly formatted tool use request.
306 <Step title="Claude responds with member tool calls" icon="wrench">
307 * Claude assesses whether acting on the desktop can help with the user's query.
308 * If so, Claude responds with one or more member `tool_use` blocks, such as `screenshot`, `left_click`, or `type`, each carrying `"toolset_name": "computer"`. A response with several of these blocks is a [batch action](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#batch-actions).
351309 * The API response has a `stop_reason` of `tool_use`, signaling a tool use request.
352310 </Step>
353311 
354 <Step title="Extract tool input, evaluate the tool on a computer, and return results" icon="computer">
355 * On your end, extract the tool name and input from Claude's request.
356 * Use the tool on a container or virtual machine.
357 * Continue the conversation with a new `user` message containing a `tool_result` content block.
312 <Step title="Run the calls in order and return results" icon="computer">
313 * Iterate over every `tool_use` block in the response, in order. For each one, dispatch on the member `name` together with `toolset_name`, and perform that action with the block's `input` on your container or virtual machine.
314 * Continue the conversation with a new `user` message that contains one `tool_result` block per `tool_use` block, matched by `tool_use_id` and each echoing `"toolset_name": "computer"`. Return an image for `screenshot` and `zoom`; a short text such as `OK` is enough for the other actions.
315 * If an action fails, return `is_error: true` for that block and answer the rest of the batch as described in [Batch actions](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#batch-actions).
358316 </Step>
359317 
360 <Step title="Claude continues calling computer use tools until it's completed the task" icon="arrows-clockwise">
361 * Claude analyzes the tool results to determine if more tool use is needed or the task has been completed.
362 * If Claude determines another tool is needed, it responds with another `tool_use` `stop_reason` and you should return to step 3.
363 * Otherwise, it crafts a text response to the user.
318 <Step title="Claude continues until the task is complete" icon="arrows-clockwise">
319 * Claude analyzes the tool results to determine if more actions are needed or the task has been completed.
320 * If Claude determines more actions are needed, it responds with another `tool_use` `stop_reason` and you should return to step 3.
321 * Otherwise, it returns a text response to the user.
364322 </Step>
365323</Steps>
366324 
367325The repetition of steps 3 and 4 without user input is referred to as the "agent loop" (that is, Claude responding with a tool use request and your application responding to Claude with the results of evaluating that request).
326 
327### Batch actions
328 
329Claude can plan a short sequence of actions, such as click, type, and then take a screenshot, and return them together in one response. This is called a batch action; it uses the same response shape as [parallel tool use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/parallel-tool-use) with one difference: you run the blocks in order rather than concurrently.
330 
331A response with a three-action batch looks like this:
332 
333```json
334{
335 "role": "assistant",
336 "content": [
337 {
338 "type": "tool_use",
339 "id": "toolu_01HqCF3nJ4Vzr8sTkPZ2wxYA",
340 "name": "left_click",
341 "toolset_name": "computer",
342 "input": { "coordinate": [640, 60] }
343 },
344 {
345 "type": "tool_use",
346 "id": "toolu_01Ppr3sZ3TnE9m6VUu4RyH2K",
347 "name": "type",
348 "toolset_name": "computer",
349 "input": { "text": "pictures of cats" }
350 },
351 {
352 "type": "tool_use",
353 "id": "toolu_01Xf5W1sD8Q9aBcJ7kLmN2pQ",
354 "name": "screenshot",
355 "toolset_name": "computer",
356 "input": {}
357 }
358 ]
359}
360```
361 
362Return one `tool_result` block for each `tool_use` block, matched by `tool_use_id`, all in the next `user` message. Every result for a member tool must carry `"toolset_name": "computer"`; a result that omits it, or that names a different toolset than its `tool_use` block, is rejected. Only `screenshot` and `zoom` results need an image; for the other members, a short text acknowledgment such as `OK` is enough (`cursor_position` returns the coordinates as text):
363 
364```json
365{
366 "role": "user",
367 "content": [
368 {
369 "type": "tool_result",
370 "tool_use_id": "toolu_01HqCF3nJ4Vzr8sTkPZ2wxYA",
371 "toolset_name": "computer",
372 "content": [{ "type": "text", "text": "OK" }]
373 },
374 {
375 "type": "tool_result",
376 "tool_use_id": "toolu_01Ppr3sZ3TnE9m6VUu4RyH2K",
377 "toolset_name": "computer",
378 "content": [{ "type": "text", "text": "OK" }]
379 },
380 {
381 "type": "tool_result",
382 "tool_use_id": "toolu_01Xf5W1sD8Q9aBcJ7kLmN2pQ",
383 "toolset_name": "computer",
384 "content": [
385 {
386 "type": "image",
387 "source": {
388 "type": "base64",
389 "media_type": "image/png",
390 "data": "iVBORw0KGgo..."
391 }
392 }
393 ]
394 }
395 ]
396}
397```
398 
399**Run blocks in order and stop at the first failure.** Later actions in a batch usually depend on earlier ones: the `type` in this example enters text into whatever the preceding click focused. Run the blocks sequentially in the order they appear in `content`, and if one fails, don't run the rest. Every `tool_use` block still needs a `tool_result`, so answer the batch as follows:
400 
401* For each action that succeeded, return its normal result.
402* For the action that failed, return `is_error: true` with a text description of what went wrong.
403* For every later action in the batch, return `is_error: true` with exactly this text (the browser use tool uses its own [halt text](https://platform.claude.com/docs/en/agents-and-tools/tool-use/browser-use-tool#batch-actions)):
404 
405```json
406{
407 "type": "tool_result",
408 "tool_use_id": "toolu_01Xf5W1sD8Q9aBcJ7kLmN2pQ",
409 "toolset_name": "computer",
410 "is_error": true,
411 "content": "Not executed: an earlier computer action in this turn failed."
412}
413```
414 
415Claude then sees which actions succeeded, which one failed, and which were skipped, and replans on its next turn. A request that leaves any `tool_use` block in the batch unanswered is rejected with an `invalid_request_error`, so an agent loop that reads only the first block fails on its next call. If your application asks a human to confirm consequential actions, make that check before each block runs, because a batch can complete a multistep action within one turn.
416 
417Claude typically finishes a batch with `screenshot` so it can observe the outcome before deciding what to do next. When a batch doesn't end with one, your application can attach a screenshot as an extra `image` block on the last result in the batch so that Claude always sees the current state of the screen, which saves a round trip compared with waiting for Claude to ask. You can also prompt Claude to end every batch with a screenshot (see [Optimize model performance with prompting](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#optimize-model-performance-with-prompting)).
368418 
369419### The computing environment
370420 
from line 443
393443 
394444## How to implement computer use
395445 
396### Start with the reference implementation
397 
398A [reference implementation](https://github.com/anthropics/anthropic-quickstarts/tree/main/computer-use-demo) is available that includes everything you need to get started with computer use:
399 
400* A [containerized environment](https://github.com/anthropics/anthropic-quickstarts/blob/main/computer-use-demo/Dockerfile) suitable for computer use with Claude
401* Implementations of [the computer use tools](https://github.com/anthropics/anthropic-quickstarts/tree/main/computer-use-demo/computer_use_demo/tools)
402* An [agent loop](https://github.com/anthropics/anthropic-quickstarts/blob/main/computer-use-demo/computer_use_demo/loop.py) that interacts with the Claude API and runs the computer use tools
403* A web interface to interact with the container, agent loop, and tools.
446Upgrading an existing `computer_20251124` integration? Start with [Migrate from `computer_20251124`](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#migrate-from-computer-20251124); the rest of this section applies to both new and migrated integrations.
447 
448<Tip>
449 The [computer use reference implementation](https://github.com/anthropics/anthropic-quickstarts/tree/main/computer-use-demo) is a complete working example: a [containerized environment](https://github.com/anthropics/anthropic-quickstarts/blob/main/computer-use-demo/Dockerfile) suitable for computer use, implementations of [the computer use tools](https://github.com/anthropics/anthropic-quickstarts/tree/main/computer-use-demo/computer_use_demo/tools), an [agent loop](https://github.com/anthropics/anthropic-quickstarts/blob/main/computer-use-demo/computer_use_demo/loop.py) that calls the Claude API and runs the tools, and a web interface for the container, loop, and tools.
450</Tip>
404451 
405452### Understand the agent loop
406453 
407The core of computer use is the "agent loop": a cycle where Claude requests tool actions, your application runs them, and returns results to Claude. The loop uses the client you created in the [Quick start](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#quick-start), a tool list shaped like the Quick start's `tools` array, and the tool-call processing helper defined in [Process Claude's tool calls](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#implement-the-computer-use-tool). Here's a simplified example:
408 
409<CodeGroup>
410 ```bash cURL
411 # The agent loop is a stateful, multi-turn pattern that doesn't translate to a
412 # one-off shell command. See the SDK tabs for the implementation.
413 ```
414 
415 ```bash CLI
416 # The agent loop is a stateful, multi-turn pattern that doesn't translate to a
417 # one-off shell command. See the SDK tabs for the implementation.
418 ```
419 
454The core of computer use is the "agent loop": a cycle where Claude requests tool actions, your application runs them, and returns results to Claude. The loop uses the client you created in the [Quick start](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#quick-start), a `tools` array that declares only the computer use toolset, and the tool-call processing helper under [Implement the computer use tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#implement-the-computer-use-tool). If you also declare other tools, such as the Quick start's bash and text editor tools, dispatch their `tool_use` blocks in the same pass; the helper answers only computer use member calls, and the loop treats a turn with no answered calls as finished. Here's a simplified example:
455 
456<CodeGroup exclude="shell">
420457 ```python Python
421 def sampling_loop(model, messages, max_iterations=10):
458 def sampling_loop(model: str, messages: list[MessageParam], max_iterations: int = 10):
422459 """
423460 Run the computer-use agent loop until Claude stops requesting tools
424461 or the iteration limit is reached.
425462 """
426463 for _ in range(max_iterations):
427 response = client.beta.messages.create(
464 response = client.messages.create(
428465 model=model,
429466 max_tokens=4096,
430467 messages=messages,
431468 tools=TOOLS,
432 betas=["computer-use-2025-11-24"],
433469 )
434470 
435471 # Add Claude's response to the conversation history
436472 messages.append({"role": "assistant", "content": response.content})
437473 
438 # Run any tools Claude requested and collect results
474 # Run the actions Claude requested, in order, and collect the results
439475 tool_results = process_tool_calls(response)
440476 if not tool_results:
441477 return messages # No more tool use; task complete
442478 
443 # Send tool results back to Claude for the next iteration
479 # Send every result back to Claude in a single user message
444480 messages.append({"role": "user", "content": tool_results})
445481 
446482 return messages
from line 485
449485 ```typescript TypeScript
450486 async function samplingLoop(
451487 model: string,
452 messages: Anthropic.Beta.BetaMessageParam[],
488 messages: Anthropic.MessageParam[],
453489 maxIterations = 10,
454 ): Promise<Anthropic.Beta.BetaMessageParam[]> {
490 ): Promise<Anthropic.MessageParam[]> {
455491 // Run the computer-use agent loop until Claude stops requesting tools
456492 // or the iteration limit is reached.
457493 for (let i = 0; i < maxIterations; i++) {
458 const response = await client.beta.messages.create({
494 const response = await client.messages.create({
459495 model,
460496 max_tokens: 4096,
461497 messages,
462498 tools,
463 betas: ["computer-use-2025-11-24"],
464499 });
465500 
466501 // Add Claude's response to the conversation history
from line 516
481516 ```
482517 
483518 ```csharp C#
484 async Task<List<BetaMessageParam>> SamplingLoop(
519 async Task<List<MessageParam>> SamplingLoop(
485520 Model model,
486 List<BetaMessageParam> messages,
521 List<MessageParam> messages,
487522 int maxIterations = 10
488523 )
489524 {
from line 526
491526 // or the iteration limit is reached.
492527 for (var i = 0; i < maxIterations; i++)
493528 {
494 var response = await client.Beta.Messages.Create(
529 var response = await client.Messages.Create(
495530 new MessageCreateParams
496531 {
497532 Model = model,
498533 MaxTokens = 4096,
499534 Messages = messages,
500535 Tools = tools,
501 Betas = ["computer-use-2025-11-24"],
502536 }
503537 );
504538 
from line 542
508542 {
509543 Role = Role.Assistant,
510544 Content = response
511 .Content.Select(block => new BetaContentBlockParam(block.Json))
545 .Content.Select(block => new ContentBlockParam(block.Json))
512546 .ToList(),
513547 }
514548 );
from line 565
531565 ```go Go
532566 // samplingLoop runs the computer-use agent loop until Claude stops
533567 // requesting tools or the iteration limit is reached.
534 func samplingLoop(ctx context.Context, model anthropic.Model, messages []anthropic.BetaMessageParam, maxIterations int) ([]anthropic.BetaMessageParam, error) {
568 func samplingLoop(ctx context.Context, model anthropic.Model, messages []anthropic.MessageParam, maxIterations int) ([]anthropic.MessageParam, error) {
535569 for range maxIterations {
536 response, err := client.Beta.Messages.New(ctx, anthropic.BetaMessageNewParams{
570 response, err := client.Messages.New(ctx, anthropic.MessageNewParams{
537571 Model: model,
538572 MaxTokens: 4096,
539573 Messages: messages,
540574 Tools: tools,
541 Betas: []anthropic.AnthropicBeta{"computer-use-2025-11-24"},
542575 })
543576 if err != nil {
544577 return nil, err
from line 580
547580 // Add Claude's response to the conversation history
548581 messages = append(messages, response.ToParam())
549582 
550 // Run any tools Claude requested and collect results
583 // Run the actions Claude requested, in order, and collect the results
551584 toolResults := processToolCalls(response)
552585 if len(toolResults) == 0 {
553586 return messages, nil // No more tool use; task complete
554587 }
555588 
556 // Send tool results back to Claude for the next iteration
557 messages = append(messages, anthropic.BetaMessageParam{
558 Role: anthropic.BetaMessageParamRoleUser,
559 Content: toolResults,
560 })
589 // Send every result back to Claude in a single user message
590 messages = append(messages, anthropic.NewUserMessage(toolResults...))
561591 }
562592 return messages, nil
563593 }
from line 599
569599 * Run the computer-use agent loop until Claude stops requesting tools
570600 * or the iteration limit is reached.
571601 */
572 List<BetaMessageParam> samplingLoop(Model model, List<BetaMessageParam> messages, int maxIterations) {
602 List<MessageParam> samplingLoop(Model model, List<MessageParam> messages, int maxIterations) {
573603 for (int i = 0; i < maxIterations; i++) {
574 BetaMessage response = client.beta().messages().create(MessageCreateParams.builder()
604 Message response = client.messages().create(MessageCreateParams.builder()
575605 .model(model)
576606 .maxTokens(4096)
577607 .messages(messages)
578 .addTool(COMPUTER_TOOL)
579 .addBeta("computer-use-2025-11-24")
608 .addTool(COMPUTER_TOOLSET)
580609 .build());
581610 
582611 // Add Claude's response to the conversation history
583 messages.add(BetaMessageParam.builder()
584 .role(BetaMessageParam.Role.ASSISTANT)
585 .contentOfBetaContentBlockParams(
586 response.content().stream().map(BetaContentBlock::toParam).toList())
612 messages.add(MessageParam.builder()
613 .role(MessageParam.Role.ASSISTANT)
614 .contentOfBlockParams(response.content().stream().map(ContentBlock::toParam).toList())
587615 .build());
588616 
589617 // Run any tools Claude requested and collect results
590 List<BetaContentBlockParam> toolResults = processToolCalls(response);
618 List<ContentBlockParam> toolResults = processToolCalls(response);
591619 if (toolResults.isEmpty()) {
592620 return messages; // No more tool use; task complete
593621 }
594622 
595623 // Send tool results back to Claude for the next iteration
596 messages.add(BetaMessageParam.builder()
597 .role(BetaMessageParam.Role.USER)
598 .contentOfBetaContentBlockParams(toolResults)
624 messages.add(MessageParam.builder()
625 .role(MessageParam.Role.USER)
626 .contentOfBlockParams(toolResults)
599627 .build());
600628 }
601629 return messages;
from line 640
612640 global $client, $tools;
613641 
614642 for ($i = 0; $i < $maxIterations; $i++) {
615 $response = $client->beta->messages->create(
643 $response = $client->messages->create(
616644 model: $model,
617645 maxTokens: 4096,
618646 messages: $messages,
619647 tools: $tools,
620 betas: ['computer-use-2025-11-24'],
621648 );
622649 
623650 // Add Claude's response to the conversation history
624 $messages[] = BetaMessageParam::with(role: Role::ASSISTANT, content: $response->content);
651 $messages[] = MessageParam::with(role: Role::ASSISTANT, content: $response->content);
625652 
626653 // Run any tools Claude requested and collect results
627654 $toolResults = processToolCalls($response);
from line 657
630657 }
631658 
632659 // Send tool results back to Claude for the next iteration
633 $messages[] = BetaMessageParam::with(role: Role::USER, content: $toolResults);
660 $messages[] = MessageParam::with(role: Role::USER, content: $toolResults);
634661 }
635662 
636663 return $messages;
from line 669
642669 # or the iteration limit is reached.
643670 def sampling_loop(model, messages, max_iterations: 10)
644671 max_iterations.times do
645 response = CLIENT.beta.messages.create(
672 response = CLIENT.messages.create(
646673 model: model,
647674 max_tokens: 4096,
648675 messages: messages,
649 tools: TOOLS,
650 betas: ["computer-use-2025-11-24"]
676 tools: TOOLS
651677 )
652678 
653679 # Add Claude's response to the conversation history
654 messages << {role: "assistant", content: response.content}
655 
656 # Run any tools Claude requested and collect results
680 messages << { role: "assistant", content: response.content }
681 
682 # Run the actions Claude requested, in order, and collect the results
657683 tool_results = process_tool_calls(response)
658684 return messages if tool_results.empty? # No more tool use; task complete
659685 
660 # Send tool results back to Claude for the next iteration
661 messages << {role: "user", content: tool_results}
686 # Send every result back to Claude in a single user message
687 messages << { role: "user", content: tool_results }
662688 end
663689 
664690 messages
from line 694
668694 
669695The loop continues until either Claude responds without requesting any tools (task completion) or the maximum iteration limit is reached. This safeguard prevents potential infinite loops that could result in unexpected API costs.
670696 
671Try the reference implementation out before reading the rest of this documentation.
672 
673697### Optimize model performance with prompting
674 
675Here are some tips on how to get the best quality outputs:
676698 
6776991. Specify simple, well-defined tasks and provide explicit instructions for each step.
6787002. Claude sometimes assumes outcomes of its actions without explicitly checking their results. To prevent this you can prompt Claude with `After each step, take a screenshot and carefully evaluate if you have achieved the right outcome. Explicitly show your thinking: "I have evaluated step X..." If not correct, try again. Only when you confirm a step was executed correctly should you move on to the next one.`
from line 702
6807024. For repeatable tasks or UI interactions, include example screenshots and tool calls of successful outcomes in your prompt.
6817035. If you need the model to log in, provide it with the username and password in your prompt inside XML tags such as `<robot_credentials>`. Using computer use within applications that require login increases the risk of bad outcomes as a result of prompt injection. Review [Mitigate jailbreaks and prompt injections](https://platform.claude.com/docs/en/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks) before providing the model with login credentials.
6827046. When constructing a user turn's `content` array, place the instruction text *before* the screenshot image. Providing the target description before the image is processed improves click accuracy.
6837. When using `computer_20251124` with `enable_zoom: true` set, Claude zooms in on a region when asked about small text or specific UI elements that aren't legible at the screenshot's default resolution, such as file names in a sidebar, tab titles, status-bar text, line numbers, or button labels. If Claude isn't zooming when you expect, ask about a specific region or element rather than the screen as a whole.
7057. Claude uses the `zoom` action to inspect a region at full resolution when asked about small text or specific UI elements that aren't legible at the screenshot's default resolution, such as file names in a sidebar, tab titles, status-bar text, line numbers, or button labels. If Claude isn't zooming when you expect, ask about a specific region or element rather than the screen as a whole.
7068. If you want every [batch action](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#batch-actions) to end with a screenshot, say so in the system prompt, for example, `End each group of actions with a screenshot so you can verify the result before continuing.`
684707 
685708<Tip>
686709 If you repeatedly encounter a clear set of issues or know in advance the tasks Claude will need to complete, use the system prompt to provide Claude with explicit tips or instructions on how to do the tasks successfully.
from line 715
692715 
693716### System prompts
694717 
695When one of the Anthropic-schema tools is requested through the Claude API, a computer use-specific system prompt is generated. It's similar to the [tool use system prompt](https://platform.claude.com/docs/en/agents-and-tools/tool-use/define-tools#tool-use-system-prompt) but starts with:
718When you include the computer use tool in a request, the API generates a computer use-specific system prompt. It's similar to the [tool use system prompt](https://platform.claude.com/docs/en/agents-and-tools/tool-use/define-tools#tool-use-system-prompt) but starts with:
696719 
697720> You have access to a set of functions you can use to answer the user's question. This includes access to a sandboxed computing environment. You do NOT currently have the ability to inspect files or interact with external resources, except by invoking the below functions.
698721 
from line 723
700723 
701724### Available actions
702725 
703The computer use tool supports these actions:
704 
705**Basic actions (all versions)**
706 
707* **screenshot:** Capture the current display
708* **left\_click:** Click at coordinates `[x, y]`
709* **type:** Type text string
710* **key:** Press key or key combination (for example, "ctrl+s")
711* **mouse\_move:** Move cursor to coordinates
712 
713**Enhanced actions (`computer_20250124` and later)** Available in `computer_20250124` and `computer_20251124`:
714 
715* **scroll:** Scroll in any direction with amount control
716* **left\_click\_drag:** Click and drag between coordinates
717* **right\_click**, **middle\_click:** Additional mouse buttons
718* **double\_click**, **triple\_click:** Multiple clicks
719* **left\_mouse\_down**, **left\_mouse\_up:** Fine-grained click control
720* **hold\_key:** Hold down a key for a specified duration (in seconds)
721* **wait:** Pause between actions
722 
723**Enhanced actions (`computer_20251124`)** Available in Claude Opus 5, Claude Sonnet 5, Claude Opus 4.8, Claude Opus 4.7, Claude Opus 4.6, Claude Sonnet 4.6, and Claude Opus 4.5:
724 
725* All actions from `computer_20250124`
726* **zoom:** View a specific region of the screen at full resolution. Requires `enable_zoom: true` in tool definition. Takes a `region` parameter with coordinates `[x1, y1, x2, y2]` defining top-left and bottom-right corners of the area to inspect.
726Each action is a member tool of the computer use toolset: Claude names the member in a `tool_use` block that carries `"toolset_name": "computer"`, and the block's `input` holds only that member's parameters, with no `action` field. The toolset has 17 member tools:
727 
728| Member | Input | Description |
729| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
730| `screenshot` | None (`{}`) | Capture the full display and return it as an image. |
731| `zoom` | `region`: `[x0, y0, x1, y1]`, the top-left and bottom-right corners of the area to inspect | Capture only that region of the display at full resolution and return it as an image, scaled to fit within your usual screenshot dimensions with its aspect ratio preserved. This lets Claude read small text or dense UI that isn't legible in a downscaled full screenshot. |
732| `left_click` | `coordinate` (optional): `[x, y]`; `text` (optional): modifier keys to hold during the click: `shift`, `ctrl`, `alt`, `super` (the Command or Windows key), or a `+`-joined combination such as `ctrl+shift` | Click the left mouse button at `coordinate`, or at the current cursor position when `coordinate` is omitted. |
733| `right_click`, `middle_click`, `double_click`, `triple_click` | Same as `left_click` | Other mouse buttons and multiple clicks. |
734| `left_click_drag` | `start_coordinate`: `[x, y]`; `coordinate`: `[x, y]`; `text` (optional): modifier keys | Press at `start_coordinate`, drag to `coordinate`, and release. |
735| `mouse_move` | `coordinate`: `[x, y]` | Move the cursor without clicking, for example, to hover. |
736| `left_mouse_down`, `left_mouse_up` | None (`{}`) | Press or release the left mouse button at the current cursor position, for drags that `left_click_drag` can't express. Move the cursor with `mouse_move` first. |
737| `cursor_position` | None (`{}`) | Report the cursor's current `[x, y]` position as text. |
738| `scroll` | `scroll_direction`: `"up"`, `"down"`, `"left"`, or `"right"`; `scroll_amount`: number of scroll-wheel clicks; `coordinate` (optional): `[x, y]`; `text` (optional): modifier keys | Scroll at `coordinate`, or at the current cursor position. |
739| `type` | `text`: the string to type | Type literal text at the current keyboard focus. |
740| `key` | `text`: a key or a `+`-joined combination such as `"Return"`, `"ctrl+s"`, or `"alt+Tab"`; `repeat` (optional): 1 to 100, default 1 | Press a key or key combination, `repeat` times. |
741| `hold_key` | `text`: a key or combination; `duration`: seconds, up to 300 | Hold a key down for the given duration. |
742| `wait` | `duration`: seconds, up to 300 | Pause before the next action, for example, while an application loads. |
743 
744Keep the following in mind when implementing the members:
745 
746* **Coordinates are in screenshot pixels.** Every `coordinate`, `start_coordinate`, and `region` value, and the position that `cursor_position` reports, is in the pixel space of the full-display screenshots you return, with the origin at the top left. Zoom images don't change this: after a `zoom`, Claude still expresses coordinates in the full screenshot's space, never relative to the zoomed image. If you scale screenshots down before returning them, scale Claude's coordinates back up before applying them to the real display (see [Size screenshots to fit image limits](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#handle-coordinate-scaling-for-higher-resolutions)).
747* **All members are enabled by default, including `zoom`.** If your environment can't produce zoom images, withhold the member with `configs` (see [Tool parameters](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#tool-parameters)) rather than leaving it enabled and returning errors. If Claude calls a member that you have withheld or don't implement, return a `tool_result` with `is_error: true` for that block.
748* **Dispatch on the pair (`toolset_name`, `name`).** `toolset_name` is what marks a block as a computer action: a custom tool in the same request can share a member's name, and a later toolset version can add members (see [Client toolsets](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-reference#client-toolsets)).
727749 
728750<Accordion title="Example actions">
729 Take a screenshot:
751 Each example is a complete `tool_use` block as it appears in Claude's response.
752 
753 Shift+click at a position, for example, to extend a selection. Unlike `hold_key`, `text` holds the modifiers only for the duration of that click or scroll:
730754 
731755 ```json
732756 {
733 "action": "screenshot"
757 "type": "tool_use",
758 "id": "toolu_01Qg8m3XqC5aRy7tD2eS4jUg",
759 "name": "left_click",
760 "toolset_name": "computer",
761 "input": { "coordinate": [500, 300], "text": "shift" }
734762 }
735763 ```
736764 
737 Click at position:
765 Drag from one point to another:
738766 
739767 ```json
740768 {
741 "action": "left_click",
742 "coordinate": [500, 300]
769 "type": "tool_use",
770 "id": "toolu_01Ed6j9VnA3yPw5rB8cQ2gSe",
771 "name": "left_click_drag",
772 "toolset_name": "computer",
773 "input": {
774 "start_coordinate": [200, 300],
775 "coordinate": [600, 300]
776 }
743777 }
744778 ```
745779 
746 Type text:
780 Scroll down three clicks of the wheel:
747781 
748782 ```json
749783 {
750 "action": "type",
751 "text": "Hello, world!"
784 "type": "tool_use",
785 "id": "toolu_01Yc5h8UmZ2xNv4qA7bP9fRd",
786 "name": "scroll",
787 "toolset_name": "computer",
788 "input": {
789 "coordinate": [500, 400],
790 "scroll_direction": "down",
791 "scroll_amount": 3
792 }
752793 }
753794 ```
754795 
755 Scroll down:
796 Press Tab four times:
756797 
757798 ```json
758799 {
759 "action": "scroll",
760 "coordinate": [500, 400],
761 "scroll_direction": "down",
762 "scroll_amount": 3
800 "type": "tool_use",
801 "id": "toolu_01Sb4g7TkY9wLu3pX6zM8eQc",
802 "name": "key",
803 "toolset_name": "computer",
804 "input": { "text": "Tab", "repeat": 4 }
763805 }
764806 ```
765807 
766 Zoom to view region in detail (Claude Opus 5, Sonnet 5, Opus 4.8, Opus 4.7, Opus 4.6, Sonnet 4.6, and Opus 4.5):
808 Zoom in to inspect a region at full resolution:
767809 
768810 ```json
769811 {
770 "action": "zoom",
771 "region": [100, 200, 400, 350]
812 "type": "tool_use",
813 "id": "toolu_01Kf7k2WpB4zQx6sC9dR3hTf",
814 "name": "zoom",
815 "toolset_name": "computer",
816 "input": { "region": [100, 200, 400, 350] }
772817 }
773818 ```
774</Accordion>
775 
776<Accordion title="Modifier keys with click and scroll actions">
777 To hold modifier keys (such as Shift, Ctrl, or Alt) while performing click or scroll actions, use the `text` parameter on those actions. This is different from `hold_key`, which holds a key for a duration without performing other actions.
778 
779 Shift+click (for example, to select a range of items):
819 
820 Report the cursor position. Answer this call with a short text result that gives the position in screenshot pixels, for example, `X=512, Y=384`:
780821 
781822 ```json
782823 {
783 "action": "left_click",
784 "coordinate": [500, 300],
785 "text": "shift"
824 "type": "tool_use",
825 "id": "toolu_01Ekh3vqB6yTs2mNc4Rw8pLd",
826 "name": "cursor_position",
827 "toolset_name": "computer",
828 "input": {}
786829 }
787830 ```
788 
789 Ctrl+click (for example, to multi-select on Windows/Linux):
790 
791 ```json
792 {
793 "action": "left_click",
794 "coordinate": [500, 300],
795 "text": "ctrl"
796 }
797 ```
798 
799 Cmd+click (for example, to multi-select on macOS):
800 
801 ```json
802 {
803 "action": "left_click",
804 "coordinate": [500, 300],
805 "text": "super"
806 }
807 ```
808 
809 Shift+scroll (for example, to scroll horizontally):
810 
811 ```json
812 {
813 "action": "scroll",
814 "coordinate": [500, 400],
815 "scroll_direction": "down",
816 "scroll_amount": 3,
817 "text": "shift"
818 }
819 ```
820 
821 The `text` parameter in click/scroll actions accepts modifier keys such as `shift`, `ctrl`, `alt`, and `super` (for the Command/Windows key).
822831</Accordion>
823832 
824833### Tool parameters
825834 
826| Parameter | Required | Description |
827| ------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- |
828| `type` | Yes | Tool version (`computer_20251124` or `computer_20250124`) |
829| `name` | Yes | Must be "computer" |
830| `display_width_px` | Yes | Display width in pixels |
831| `display_height_px` | Yes | Display height in pixels |
832| `display_number` | No | Display number for X11 environments |
833| `enable_zoom` | No | Enable zoom action (`computer_20251124` only). Set to `true` to allow Claude to zoom into specific screen regions. Default: `false` |
834 
835<Note>
836 **Important:** Your application must explicitly run the computer use tool; Claude cannot run it directly. You are responsible for implementing the screenshot capture, mouse movements, keyboard inputs, and other actions based on Claude's requests.
837</Note>
835The toolset entry in the `tools` array accepts four parameters; the rules they share with the browser use toolset are listed under [Client toolsets](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-reference#client-toolsets).
836 
837| Parameter | Required | Description |
838| ----------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
839| `type` | Yes | `computer_toolset_20260801` |
840| `configs` | No | Per-member settings keyed by member name; each member accepts `enabled` (default `true` for all 17, including `zoom`) and `defer_loading` (default `false`, for [tool search](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool#deferred-tool-loading)), and members you omit keep their defaults. |
841| `cache_control` | No | [Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) breakpoint at the toolset definition; entry only. A breakpoint on any `tool_use` or `tool_result` block in a batch takes effect at the end of that batch; see [Tool use with prompt caching](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-use-with-prompt-caching#cache-control-on-tool-definitions). |
842| `allowed_callers` | No | `["direct"]` only. |
843 
844For example, this entry withholds `zoom` for an environment that doesn't implement it and sets a cache breakpoint at the toolset definition:
845 
846```json
847{
848 "type": "computer_toolset_20260801",
849 "configs": {
850 "zoom": { "enabled": false }
851 },
852 "cache_control": { "type": "ephemeral" }
853}
854```
855 
856If your agent loop can run only one action per round trip, set `disable_parallel_tool_use` to `true` in `tool_choice`; Claude then returns at most one member `tool_use` block per turn (see [Disable parallel tool use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/parallel-tool-use#disable-parallel-tool-use)).
857 
858The entry rejects these parameters from earlier tool versions, and a request that includes any of them returns an `invalid_request_error`:
859 
860* `name`: member names are fixed by the toolset version.
861* `display_width_px`, `display_height_px`, and `display_number`: coordinates are always in the pixel space of the screenshots you return.
862* `enable_zoom`: zoom is a member tool that you control through `configs`.
863 
864The entry also can't be declared in the same request as a `computer_20251124` entry or another tool named `computer`. For `strict`, `input_examples`, `defer_loading` placement, `tool_choice`, streaming, and caller restrictions, see [Client toolsets](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-reference#client-toolsets).
838865 
839866### Combining with thinking
840867 
841868For combining computer use with thinking, see [Thinking](https://platform.claude.com/docs/en/build-with-claude/thinking).
842869 
843870<Tip>
844 For computer use specifically, internal benchmarking suggests these `effort` settings:
871 For the earlier `computer_20251124` tool, internal benchmarking on the models that use it suggests these `effort` settings:
845872 
846873 * **Claude Opus 4.7:** use `high` as the default; use `low` for high-throughput or cost-sensitive workloads.
847874 * **Claude Sonnet 4.6 and Claude Opus 4.6:** use `medium` as the default (best accuracy-to-cost ratio). Avoid `max`, which adds token cost without improving accuracy on UI tasks. On these models, `low` uses *fewer* output tokens than disabling thinking entirely (fewer mistakes mean fewer retries), making it a strong option for cost-sensitive loops.
from line 878
851878 
852879To add other tools alongside computer use, include them in the same `tools` array. The [Quick start](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#quick-start) section shows this pattern with the [bash tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/bash-tool) and [text editor tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/text-editor-tool). You can add your own [custom tool definitions](https://platform.claude.com/docs/en/agents-and-tools/tool-use/define-tools) the same way.
853880 
881For tasks that stay inside webpages, you can also [declare the browser use tool in the same request](https://platform.claude.com/docs/en/agents-and-tools/tool-use/browser-use-tool#combine-with-other-tools): the two toolsets work independently, each in its own coordinate frame, and calls to members that share a name, such as `screenshot` or `key`, are told apart by `toolset_name`.
882 
854883### Build a custom computer use environment
855884 
856885The [reference implementation](https://github.com/anthropics/anthropic-quickstarts/tree/main/computer-use-demo) is meant to help you get started with computer use. It includes all of the components needed to have Claude use a computer. However, you can build your own environment for computer use to suit your needs. You'll need:
857886 
858887* A virtualized or containerized environment suitable for computer use with Claude
859* An implementation of at least one of the Anthropic-schema computer use tools
888* An implementation of the computer use tool's actions
860889* An agent loop that interacts with the Claude API and runs the `tool_use` results using your tool implementations
861890* An API or UI that allows user input to start the agent loop
862891 
863#### Implement the computer use tool
892### Implement the computer use tool
864893 
865894The computer use tool is implemented as a schema-less tool. When using this tool, you don't need to provide an input schema as with other tools; the schema is built into Claude's model and can't be modified.
866895 
from line 901
872901 <Step title="Implement action handlers">
873902 Create functions to handle each action type that Claude might request:
874903 
875 <CodeGroup>
876 ```bash cURL
877 # This is application-side helper code with no API request. See the SDK tabs
878 # for the pattern.
879 ```
880 
881 ```bash CLI
882 # This is application-side helper code with no API request. See the SDK tabs
883 # for the pattern.
884 ```
885 
904 <CodeGroup exclude="shell">
886905 ```python Python
887 def capture_screenshot():
888 return "<screenshot data>"
889 
890 
891 def click_at(x, y):
906 # Placeholder image data; a real executor captures the screen and returns the PNG bytes
907 PLACEHOLDER_PNG = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
908 
909 
910 def capture_screenshot() -> list[ImageBlockParam]:
911 # screenshot answers with an image block rather than text: return the result content list
912 return [
913 {
914 "type": "image",
915 "source": {"type": "base64", "media_type": "image/png", "data": PLACEHOLDER_PNG},
916 }
917 ]
918 
919 
920 def click(coordinate=None):
921 if coordinate is None:
922 return "clicked at current cursor"
923 x, y = coordinate
892924 return f"clicked at ({x}, {y})"
893925 
894926 
from line 928
896928 return f"typed: {text}"
897929 
898930 
899 def handle_computer_action(action_type, params):
900 if action_type == "screenshot":
931 def handle_computer_action(name, tool_input):
932 if name == "screenshot":
901933 return capture_screenshot()
902 elif action_type == "left_click":
903 x, y = params["coordinate"]
904 return click_at(x, y)
905 elif action_type == "type":
906 return type_text(params["text"])
934 elif name == "left_click":
935 # coordinate is optional; without it, click where the cursor already is
936 return click(tool_input.get("coordinate"))
937 elif name == "type":
938 return type_text(tool_input["text"])
907939 # Handle other actions as needed
908 return f"unhandled action: {action_type}"
940 raise ValueError(f"Unknown or unimplemented member: {name}")
909941 ```
910942 
911943 ```typescript TypeScript
912 function captureScreenshot(): string {
913 return "<screenshot data>";
944 // Placeholder image data; a real executor captures the screen as PNG bytes
945 const PLACEHOLDER_PNG = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==";
946 
947 function captureScreenshot(): Anthropic.ImageBlockParam[] {
948 // screenshot answers with an image block rather than text
949 return [
950 {
951 type: "image",
952 source: {
953 type: "base64",
954 media_type: "image/png",
955 data: PLACEHOLDER_PNG,
956 },
957 },
958 ];
914959 }
915960 
916961 function clickAt(x: number, y: number): string {
917962 return `clicked at (${x}, ${y})`;
918963 }
919964 
965 function clickAtCursor(): string {
966 return "clicked at the current cursor position";
967 }
968 
920969 function typeText(text: string): string {
921970 return `typed: ${text}`;
922971 }
923972 
924973 function handleComputerAction(
925 actionType: string,
926 params: Record<string, unknown>,
927 ): string {
928 if (actionType === "screenshot") {
974 action: string,
975 input: unknown,
976 ): string | Anthropic.ImageBlockParam[] {
977 const params: object =
978 typeof input === "object" && input !== null ? input : {};
979 if (action === "screenshot") {
929980 return captureScreenshot();
930 } else if (actionType === "left_click") {
931 const [x, y] = params.coordinate as [number, number];
932 return clickAt(x, y);
933 } else if (actionType === "type") {
934 return typeText(params.text as string);
981 } else if (action === "left_click") {
982 // coordinate is optional on the toolset; without one, click at the cursor
983 if ("coordinate" in params && Array.isArray(params.coordinate)) {
984 const [x, y] = params.coordinate;
985 return clickAt(x, y);
986 }
987 return clickAtCursor();
988 } else if (action === "type" && "text" in params) {
989 return typeText(String(params.text));
935990 }
936991 // Handle other actions as needed
937 return `unhandled action: ${actionType}`;
992 throw new Error(`Unknown or unimplemented member: ${action}`);
938993 }
939994 ```
940995 
941996 ```csharp C#
942 string CaptureScreenshot() => "<screenshot data>";
997 // Placeholder image data; a real executor captures the screen and returns the PNG bytes
998 const string PlaceholderPng = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==";
999 
1000 // screenshot answers with an image block rather than text: return the result content list
1001 List<Block> CaptureScreenshot() =>
1002 [
1003 new ImageBlockParam(
1004 new Base64ImageSource { Data = PlaceholderPng, MediaType = MediaType.ImagePng }
1005 ),
1006 ];
9431007 
9441008 string ClickAt(int x, int y) => $"clicked at ({x}, {y})";
9451009 
1010 string ClickAtCursor() => "clicked at the current cursor position";
1011 
9461012 string TypeText(string text) => $"typed: {text}";
9471013 
948 string HandleComputerAction(string actionType, IReadOnlyDictionary<string, JsonElement> input) =>
949 actionType switch
1014 ToolResultBlockParamContent HandleComputerAction(
1015 string action,
1016 IReadOnlyDictionary<string, JsonElement> input
1017 ) =>
1018 action switch
9501019 {
9511020 "screenshot" => CaptureScreenshot(),
952 "left_click" => ClickAt(
953 input["coordinate"][0].GetInt32(),
954 input["coordinate"][1].GetInt32()
1021 // coordinate is optional on click members; without it, click where the cursor is
1022 "left_click" when input.TryGetValue("coordinate", out var xy) => ClickAt(
1023 xy[0].GetInt32(),
1024 xy[1].GetInt32()
9551025 ),
1026 "left_click" => ClickAtCursor(),
9561027 "type" => TypeText(input["text"].GetString()!),
9571028 // Handle other actions as needed
958 _ => $"unhandled action: {actionType}",
1029 _ => throw new NotSupportedException($"Unknown or unimplemented member: {action}"),
9591030 };
9601031 ```
9611032 
9621033 ```go Go
963 func captureScreenshot() string {
964 return "<screenshot data>"
1034 // placeholderPNG stands in for a real capture: an executor returns the
1035 // screen as base64-encoded PNG data.
1036 const placeholderPNG = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
1037 
1038 // captureScreenshot returns an image block rather than text.
1039 func captureScreenshot() []anthropic.ToolResultBlockParamContentUnion {
1040 return []anthropic.ToolResultBlockParamContentUnion{{
1041 OfImage: &anthropic.ImageBlockParam{
1042 Source: anthropic.ImageBlockParamSourceUnion{
1043 OfBase64: &anthropic.Base64ImageSourceParam{
1044 MediaType: anthropic.Base64ImageSourceMediaTypeImagePNG,
1045 Data: placeholderPNG,
1046 },
1047 },
1048 },
1049 }}
1050 }
1051 
1052 // textContent wraps text as tool_result content.
1053 func textContent(text string) []anthropic.ToolResultBlockParamContentUnion {
1054 return []anthropic.ToolResultBlockParamContentUnion{
1055 {OfText: &anthropic.TextBlockParam{Text: text}},
1056 }
9651057 }
9661058 
9671059 func clickAt(x, y int) string {
9681060 return fmt.Sprintf("clicked at (%d, %d)", x, y)
9691061 }
9701062 
1063 func clickAtCursor() string {
1064 return "clicked at the current cursor position"
1065 }
1066 
9711067 func typeText(text string) string {
9721068 return fmt.Sprintf("typed: %s", text)
9731069 }
9741070 
975 func handleComputerAction(actionType string, params map[string]any) string {
976 switch actionType {
1071 func handleComputerAction(action string, params map[string]any) ([]anthropic.ToolResultBlockParamContentUnion, error) {
1072 switch action {
9771073 case "screenshot":
978 return captureScreenshot()
1074 return captureScreenshot(), nil
9791075 case "left_click":
980 coord := params["coordinate"].([]any)
981 return clickAt(int(coord[0].(float64)), int(coord[1].(float64)))
1076 // coordinate is optional; without it, click where the cursor already is
1077 coord, ok := params["coordinate"].([]any)
1078 if !ok {
1079 return textContent(clickAtCursor()), nil
1080 }
1081 if len(coord) == 2 {
1082 x, xok := coord[0].(float64)
1083 y, yok := coord[1].(float64)
1084 if xok && yok {
1085 return textContent(clickAt(int(x), int(y))), nil
1086 }
1087 }
9821088 case "type":
983 return typeText(params["text"].(string))
1089 if text, ok := params["text"].(string); ok {
1090 return textContent(typeText(text)), nil
1091 }
9841092 // Handle other actions as needed
9851093 default:
986 return fmt.Sprintf("unhandled action: %s", actionType)
1094 return nil, fmt.Errorf("unknown or unimplemented member: %s", action)
9871095 }
1096 // Reached when a member's input is missing a field or a field has the wrong type
1097 return nil, fmt.Errorf("invalid input for %s", action)
9881098 }
9891099 
9901100 ```
9911101 
9921102 ```java Java
993 String captureScreenshot() {
994 return "<screenshot data>";
1103 /** Placeholder pixels; a real executor captures the screen and base64-encodes the PNG. */
1104 static final String PLACEHOLDER_PNG = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==";
1105 
1106 ToolResultBlockParam.Content captureScreenshot() {
1107 ImageBlockParam image = ImageBlockParam.builder()
1108 .source(Base64ImageSource.builder()
1109 .mediaType(Base64ImageSource.MediaType.IMAGE_PNG)
1110 .data(PLACEHOLDER_PNG)
1111 .build())
1112 .build();
1113 return ToolResultBlockParam.Content.ofBlocks(
1114 List.of(ToolResultBlockParam.Content.Block.ofImage(image)));
9951115 }
9961116 
9971117 String clickAt(long x, long y) {
9981118 return "clicked at (" + x + ", " + y + ")";
9991119 }
10001120 
1121 String clickAtCursor() {
1122 return "clicked at current cursor";
1123 }
1124 
10011125 String typeText(String text) {
10021126 return "typed: " + text;
10031127 }
10041128 
1005 String handleComputerAction(String actionType, Map<String, JsonValue> params) {
1006 return switch (actionType) {
1007 case "screenshot" -> captureScreenshot();
1129 /** Runs one computer toolset member; {@code action} is the tool_use block's name. */
1130 ToolResultBlockParam.Content handleComputerAction(String action, Map<String, JsonValue> input) {
1131 if (action.equals("screenshot")) {
1132 return captureScreenshot(); // the one member here that answers with an image block
1133 }
1134 String output = switch (action) {
10081135 case "left_click" -> {
1009 List<JsonValue> coordinate = (List<JsonValue>) params.get("coordinate").asArray().get();
1010 long x = ((Number) coordinate.get(0).asNumber().get()).longValue();
1011 long y = ((Number) coordinate.get(1).asNumber().get()).longValue();
1136 JsonValue coordinate = input.get("coordinate"); // optional on the toolset
1137 if (coordinate == null) {
1138 yield clickAtCursor();
1139 }
1140 List<JsonValue> point = (List<JsonValue>) coordinate.asArray().get();
1141 long x = ((Number) point.get(0).asNumber().get()).longValue();
1142 long y = ((Number) point.get(1).asNumber().get()).longValue();
10121143 yield clickAt(x, y);
10131144 }
1014 case "type" -> typeText(params.get("text").asStringOrThrow());
1145 case "type" -> typeText(input.get("text").asStringOrThrow());
10151146 // Handle other actions as needed
1016 default -> "unhandled action: " + actionType;
1147 default -> throw new UnsupportedOperationException("Unknown or unimplemented member: " + action);
10171148 };
1149 return ToolResultBlockParam.Content.ofString(output);
10181150 }
10191151 ```
10201152 
10211153 ```php PHP
1022 function captureScreenshot(): string
1154 // Stand-in for real PNG bytes; a real executor captures the screen
1155 const PLACEHOLDER_PNG = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==';
1156 
1157 function captureScreenshot(): array
10231158 {
1024 return '<screenshot data>';
1025 }
1026 
1027 function clickAt(int $x, int $y): string
1159 // screenshot answers with an image block rather than text, so return the result content list
1160 $image = [
1161 'type' => 'image',
1162 'source' => ['type' => 'base64', 'media_type' => 'image/png', 'data' => PLACEHOLDER_PNG],
1163 ];
1164 
1165 return [$image];
1166 }
1167 
1168 function clickAt(?array $coordinate): string
10281169 {
1170 // left_click may omit coordinate, in which case the click lands where the cursor already is
1171 if ($coordinate === null) {
1172 return 'clicked at current cursor';
1173 }
1174 [$x, $y] = $coordinate;
1175 
10291176 return "clicked at ({$x}, {$y})";
10301177 }
10311178 
from line 1181
10341181 return "typed: {$text}";
10351182 }
10361183 
1037 function handleComputerAction(string $actionType, array $params): string
1184 function handleComputerAction(string $name, array $input): string|array
10381185 {
1039 return match ($actionType) {
1186 return match ($name) {
10401187 'screenshot' => captureScreenshot(),
1041 'left_click' => clickAt(...$params['coordinate']),
1042 'type' => typeText($params['text']),
1188 'left_click' => clickAt($input['coordinate'] ?? null),
1189 'type' => typeText($input['text']),
10431190 // Handle other actions as needed
1044 default => "unhandled action: {$actionType}",
1191 default => throw new RuntimeException("Unknown or unimplemented member: {$name}"),
10451192 };
10461193 }
10471194 ```
10481195 
10491196 ```ruby Ruby
1197 # Stand-in image data; a real executor captures the screen as a PNG.
1198 PLACEHOLDER_PNG = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
1199 
1200 # screenshot answers with an image block rather than text
10501201 def capture_screenshot
1051 "<screenshot data>"
1202 [
1203 {
1204 type: "image",
1205 source: { type: "base64", media_type: "image/png", data: PLACEHOLDER_PNG }
1206 }
1207 ]
10521208 end
10531209 
1054 def click_at(x, y)
1210 def click(coordinate = nil)
1211 return "clicked at current cursor" if coordinate.nil?
1212 
1213 x, y = coordinate
10551214 "clicked at (#{x}, #{y})"
10561215 end
10571216 
from line 1218
10591218 "typed: #{text}"
10601219 end
10611220 
1062 def handle_computer_action(action_type, params)
1063 case action_type
1221 def handle_computer_action(name, input)
1222 case name
10641223 when "screenshot"
10651224 capture_screenshot
10661225 when "left_click"
1067 x, y = params[:coordinate]
1068 click_at(x, y)
1226 # coordinate is optional; without it, click where the cursor already is
1227 click(input[:coordinate])
10691228 when "type"
1070 type_text(params[:text])
1229 type_text(input[:text])
10711230 # Handle other actions as needed
10721231 else
1073 "unhandled action: #{action_type}"
1232 raise ArgumentError, "Unknown or unimplemented member: #{name}"
10741233 end
10751234 end
10761235 ```
from line 1239
10801239 <Step title="Process Claude's tool calls">
10811240 Extract and run tool calls from Claude's responses:
10821241 
1083 <CodeGroup>
1084 ```bash cURL
1085 # This is application-side helper code with no API request. See the SDK tabs
1086 # for the pattern.
1087 ```
1088 
1089 ```bash CLI
1090 # This is application-side helper code with no API request. See the SDK tabs
1091 # for the pattern.
1092 ```
1093 
1242 <CodeGroup exclude="shell">
10941243 ```python Python
1095 def process_tool_calls(response):
1096 tool_results = []
1244 NOT_EXECUTED = "Not executed: an earlier computer action in this turn failed."
1245 
1246 
1247 def process_tool_calls(response: Message) -> list[ToolResultBlockParam]:
1248 """
1249 Run the computer actions in Claude's response in order and answer each
1250 one. After the first failure the rest are skipped, because Claude planned
1251 them assuming the earlier actions succeeded.
1252 """
1253 tool_results: list[ToolResultBlockParam] = []
1254 failed = False
10971255 for block in response.content:
1098 if block.type == "tool_use":
1099 action = block.input["action"]
1100 result = handle_computer_action(action, block.input)
1101 tool_results.append(
1102 {
1103 "type": "tool_result",
1104 "tool_use_id": block.id,
1105 "content": result,
1106 }
1107 )
1256 # Only the computer toolset is declared; route other tools here if you add them
1257 if block.type != "tool_use" or block.toolset_name != "computer":
1258 continue
1259 result: ToolResultBlockParam = {
1260 "type": "tool_result",
1261 "tool_use_id": block.id,
1262 "toolset_name": "computer",
1263 }
1264 if failed:
1265 result["content"] = NOT_EXECUTED
1266 result["is_error"] = True
1267 else:
1268 try:
1269 # A string, or a list of content blocks such as the screenshot image
1270 result["content"] = handle_computer_action(block.name, block.input)
1271 except Exception as err:
1272 result["content"] = f"Error: {err}"
1273 result["is_error"] = True
1274 failed = True
1275 tool_results.append(result)
11081276 return tool_results
11091277 ```
11101278 
11111279 ```typescript TypeScript
1280 const HALT_TEXT =
1281 "Not executed: an earlier computer action in this turn failed.";
1282 
1283 function computerResult(
1284 toolUseId: string,
1285 content: string | Anthropic.ImageBlockParam[],
1286 isError?: boolean,
1287 ): Anthropic.ToolResultBlockParam {
1288 return {
1289 type: "tool_result",
1290 tool_use_id: toolUseId,
1291 toolset_name: "computer",
1292 content,
1293 is_error: isError,
1294 };
1295 }
1296 
11121297 function processToolCalls(
1113 response: Anthropic.Beta.BetaMessage,
1114 ): Anthropic.Beta.BetaToolResultBlockParam[] {
1115 const toolResults: Anthropic.Beta.BetaToolResultBlockParam[] = [];
1298 response: Anthropic.Message,
1299 ): Anthropic.ToolResultBlockParam[] {
1300 const toolResults: Anthropic.ToolResultBlockParam[] = [];
1301 let failed = false;
11161302 for (const block of response.content) {
1117 if (block.type === "tool_use") {
1118 const input = block.input as Record<string, unknown>;
1119 const action = input.action as string;
1120 const result = handleComputerAction(action, input);
1121 toolResults.push({
1122 type: "tool_result",
1123 tool_use_id: block.id,
1124 content: result,
1125 });
1303 if (block.type !== "tool_use") {
1304 continue;
1305 }
1306 if (block.toolset_name !== "computer") {
1307 // This example declares only the computer toolset; route other tools
1308 // here if you add them.
1309 continue;
1310 }
1311 if (failed) {
1312 // A batch stops at its first failure; answer later actions unexecuted
1313 toolResults.push(computerResult(block.id, HALT_TEXT, true));
1314 continue;
1315 }
1316 try {
1317 // A string, or the image block list that screenshot returns
1318 const result = handleComputerAction(block.name, block.input);
1319 toolResults.push(computerResult(block.id, result));
1320 } catch (error) {
1321 failed = true;
1322 const message = error instanceof Error ? error.message : String(error);
1323 toolResults.push(computerResult(block.id, `Error: ${message}`, true));
11261324 }
11271325 }
11281326 return toolResults;
from line 1328
11301328 ```
11311329 
11321330 ```csharp C#
1133 List<BetaContentBlockParam> ProcessToolCalls(BetaMessage response)
1331 const string HaltText = "Not executed: an earlier computer action in this turn failed.";
1332 
1333 List<ContentBlockParam> ProcessToolCalls(Message response)
11341334 {
1135 List<BetaContentBlockParam> toolResults = [];
1335 List<ContentBlockParam> toolResults = [];
1336 var failed = false;
11361337 foreach (var block in response.Content)
11371338 {
1138 if (block.TryPickToolUse(out var toolUse))
1339 if (!block.TryPickToolUse(out var toolUse))
11391340 {
1140 var action = toolUse.Input["action"].GetString()!;
1141 var result = HandleComputerAction(action, toolUse.Input);
1142 toolResults.Add(new BetaToolResultBlockParam(toolUse.ID) { Content = result });
1341 continue;
1342 }
1343 
1344 if (toolUse.ToolsetName != "computer")
1345 {
1346 // This example declares only the computer toolset; route other tools
1347 // here if you add them.
1348 continue;
1349 }
1350 
1351 if (failed)
1352 {
1353 // A batch stops at its first failure; answer later actions without running them
1354 toolResults.Add(
1355 new ToolResultBlockParam(toolUse.ID)
1356 {
1357 Content = HaltText,
1358 IsError = true,
1359 ToolsetName = "computer",
1360 }
1361 );
1362 continue;
1363 }
1364 
1365 try
1366 {
1367 // A string, or the image block list that screenshot returns
1368 var result = HandleComputerAction(toolUse.Name, toolUse.Input);
1369 toolResults.Add(
1370 new ToolResultBlockParam(toolUse.ID) { Content = result, ToolsetName = "computer" }
1371 );
1372 }
1373 catch (Exception e)
1374 {
1375 failed = true;
1376 toolResults.Add(
1377 new ToolResultBlockParam(toolUse.ID)
1378 {
1379 Content = $"Error: {e.Message}",
1380 IsError = true,
1381 ToolsetName = "computer",
1382 }
1383 );
11431384 }
11441385 }
11451386 return toolResults;
from line 1388
11471388 ```
11481389 
11491390 ```go Go
1150 func processToolCalls(response *anthropic.BetaMessage) []anthropic.BetaContentBlockParamUnion {
1151 var toolResults []anthropic.BetaContentBlockParamUnion
1391 const notExecuted = "Not executed: an earlier computer action in this turn failed."
1392 
1393 // computerToolResult builds the result for one computer action. Unlike an
1394 // ordinary tool result, it must echo the toolset name.
1395 func computerToolResult(toolUseID string, content []anthropic.ToolResultBlockParamContentUnion, isError bool) anthropic.ContentBlockParamUnion {
1396 result := anthropic.ToolResultBlockParam{
1397 ToolUseID: toolUseID,
1398 ToolsetName: anthropic.String("computer"),
1399 Content: content,
1400 }
1401 if isError {
1402 result.IsError = anthropic.Bool(true)
1403 }
1404 return anthropic.ContentBlockParamUnion{OfToolResult: &result}
1405 }
1406 
1407 // processToolCalls runs the computer actions in Claude's response in order and
1408 // builds one tool_result per tool_use block. After the first failure it skips
1409 // the rest: Claude planned them assuming the earlier actions succeeded.
1410 func processToolCalls(response *anthropic.Message) []anthropic.ContentBlockParamUnion {
1411 var toolResults []anthropic.ContentBlockParamUnion
1412 failed := false
11521413 for _, block := range response.Content {
11531414 switch variant := block.AsAny().(type) {
1154 case anthropic.BetaToolUseBlock:
1155 input := variant.Input.(map[string]any)
1156 action := input["action"].(string)
1157 result := handleComputerAction(action, input)
1158 toolResults = append(toolResults, anthropic.NewBetaToolResultBlock(variant.ID, result, false))
1415 case anthropic.ToolUseBlock:
1416 // This example declares only the computer toolset; route other tools here if you add them.
1417 if variant.ToolsetName != "computer" {
1418 continue
1419 }
1420 if failed {
1421 toolResults = append(toolResults, computerToolResult(variant.ID, textContent(notExecuted), true))
1422 continue
1423 }
1424 var input map[string]any
1425 var content []anthropic.ToolResultBlockParamContentUnion
1426 err := json.Unmarshal(variant.Input, &input)
1427 if err == nil {
1428 // Text, or the image block that screenshot returns
1429 content, err = handleComputerAction(variant.Name, input)
1430 }
1431 if err != nil {
1432 failed = true
1433 content = textContent("Error: " + err.Error())
1434 }
1435 toolResults = append(toolResults, computerToolResult(variant.ID, content, err != nil))
11591436 }
11601437 }
11611438 return toolResults
from line 1441
11641441 ```
11651442 
11661443 ```java Java
1167 List<BetaContentBlockParam> processToolCalls(BetaMessage response) {
1168 List<BetaContentBlockParam> toolResults = new ArrayList<>();
1169 for (BetaContentBlock block : response.content()) {
1170 if (block.isToolUse()) {
1171 BetaToolUseBlock toolUse = block.asToolUse();
1172 Map<String, JsonValue> input =
1173 (Map<String, JsonValue>) toolUse._input().asObject().get();
1174 String action = input.get("action").asStringOrThrow();
1175 String result = handleComputerAction(action, input);
1176 toolResults.add(BetaContentBlockParam.ofToolResult(
1177 BetaToolResultBlockParam.builder()
1178 .toolUseId(toolUse.id())
1179 .content(result)
1180 .build()));
1444 /** The exact text the toolset contract prescribes for member calls skipped after a failure. */
1445 static final String HALT_TEXT = "Not executed: an earlier computer action in this turn failed.";
1446 
1447 /** Every result answering a computer toolset member echoes toolset_name. */
1448 ToolResultBlockParam.Builder computerResult(ToolUseBlock toolUse) {
1449 return ToolResultBlockParam.builder()
1450 .toolUseId(toolUse.id())
1451 .toolsetName("computer");
1452 }
1453 
1454 /**
1455 * Run the computer actions in Claude's response in order and build one
1456 * tool_result per tool_use block. After the first failure, skip the rest:
1457 * Claude planned them assuming the earlier actions succeeded.
1458 */
1459 List<ContentBlockParam> processToolCalls(Message response) {
1460 List<ContentBlockParam> toolResults = new ArrayList<>();
1461 boolean failed = false;
1462 for (ContentBlock block : response.content()) {
1463 // This example declares only the computer toolset; route other tools here if you add them.
1464 if (!block.isToolUse() || !block.asToolUse().toolsetName().equals(Optional.of("computer"))) {
1465 continue;
1466 }
1467 ToolUseBlock toolUse = block.asToolUse();
1468 ToolResultBlockParam result;
1469 if (failed) {
1470 result = computerResult(toolUse).content(HALT_TEXT).isError(true).build();
1471 } else {
1472 try {
1473 Map<String, JsonValue> input =
1474 (Map<String, JsonValue>) toolUse._input().asObject().get();
1475 // A string, or the image block that screenshot returns
1476 ToolResultBlockParam.Content output = handleComputerAction(toolUse.name(), input);
1477 result = computerResult(toolUse).content(output).build();
1478 } catch (RuntimeException e) {
1479 failed = true;
1480 result = computerResult(toolUse).content("Error: " + e.getMessage()).isError(true).build();
1481 }
1482 }
1483 toolResults.add(ContentBlockParam.ofToolResult(result));
1484 }
1485 return toolResults;
1486 }
1487 ```
1488 
1489 ```php PHP
1490 const HALT_TEXT = 'Not executed: an earlier computer action in this turn failed.';
1491 
1492 function processToolCalls(Message $response): array
1493 {
1494 $toolResults = [];
1495 $failed = false;
1496 foreach ($response->content as $block) {
1497 // This example declares only the computer toolset; route other tools here if you add them.
1498 // Read toolset_name through array access: the SDK keeps it as raw data until a release types it.
1499 if (!($block instanceof ToolUseBlock) || ($block['toolsetName'] ?? $block['toolset_name'] ?? null) !== 'computer') {
1500 continue;
1501 }
1502 $result = ['type' => 'tool_result', 'tool_use_id' => $block->id, 'toolset_name' => 'computer'];
1503 if ($failed) {
1504 // A batch stops at its first failure; the remaining actions are answered without running
1505 $toolResults[] = [...$result, 'content' => HALT_TEXT, 'is_error' => true];
1506 continue;
1507 }
1508 try {
1509 // A string, or the image block list that screenshot returns
1510 $toolResults[] = [...$result, 'content' => handleComputerAction($block->name, $block->input)];
1511 } catch (Throwable $e) {
1512 $failed = true;
1513 $toolResults[] = [...$result, 'content' => 'Error: ' . $e->getMessage(), 'is_error' => true];
11811514 }
11821515 }
1183 return toolResults;
1184 }
1185 ```
1186 
1187 ```php PHP
1188 function processToolCalls(BetaMessage $response): array
1189 {
1190 $toolResults = [];
1191 foreach ($response->content as $block) {
1192 if ($block instanceof BetaToolUseBlock) {
1193 $action = $block->input['action'];
1194 $result = handleComputerAction($action, $block->input);
1195 $toolResults[] = BetaToolResultBlockParam::with(
1196 toolUseID: $block->id,
1197 content: $result,
1198 );
1199 }
1200 }
1516 
12011517 return $toolResults;
12021518 }
12031519 ```
12041520 
12051521 ```ruby Ruby
1522 NOT_EXECUTED = "Not executed: an earlier computer action in this turn failed."
1523 
1524 # Run the computer actions in Claude's response in order and build one
1525 # tool_result per tool_use block. After the first failure, skip the rest:
1526 # Claude planned them assuming the earlier actions succeeded.
12061527 def process_tool_calls(response)
12071528 tool_results = []
1529 failed = false
12081530 response.content.each do |block|
1209 next unless block.type == :tool_use
1210 
1211 action = block.input[:action]
1212 result = handle_computer_action(action, block.input)
1213 tool_results << {
1214 type: "tool_result",
1215 tool_use_id: block.id,
1216 content: result
1217 }
1531 # This example declares only the computer toolset; route other tools here
1532 # if you add them.
1533 next unless block.type == :tool_use && block.toolset_name == "computer"
1534 
1535 result = { type: "tool_result", tool_use_id: block.id, toolset_name: "computer" }
1536 if failed
1537 result.update(content: NOT_EXECUTED, is_error: true)
1538 else
1539 begin
1540 # A String, or the image content blocks that screenshot returns
1541 result[:content] = handle_computer_action(block.name, block.input)
1542 rescue => e
1543 result.update(content: "Error: #{e.message}", is_error: true)
1544 failed = true
1545 end
1546 end
1547 tool_results << result
12181548 end
12191549 tool_results
12201550 end
from line 1553
12231553 </Step>
12241554 
12251555 <Step title="Implement the agent loop">
1226 Create a loop that continues until Claude completes the task:
1227 
1228 <CodeGroup>
1229 ```bash cURL
1230 # The agent loop is a stateful, multi-turn pattern that doesn't translate to a
1231 # one-off shell command. See the SDK tabs for the implementation.
1232 ```
1233 
1234 ```bash CLI
1235 # The agent loop is a stateful, multi-turn pattern that doesn't translate to a
1236 # one-off shell command. See the SDK tabs for the implementation.
1237 ```
1238 
1239 ```python Python
1240 def sampling_loop(model, messages, max_iterations=10):
1241 """
1242 Run the computer-use agent loop until Claude stops requesting tools
1243 or the iteration limit is reached.
1244 """
1245 for _ in range(max_iterations):
1246 response = client.beta.messages.create(
1247 model=model,
1248 max_tokens=4096,
1249 messages=messages,
1250 tools=TOOLS,
1251 betas=["computer-use-2025-11-24"],
1252 )
1253 
1254 # Add Claude's response to the conversation history
1255 messages.append({"role": "assistant", "content": response.content})
1256 
1257 # Run any tools Claude requested and collect results
1258 tool_results = process_tool_calls(response)
1259 if not tool_results:
1260 return messages # No more tool use; task complete
1261 
1262 # Send tool results back to Claude for the next iteration
1263 messages.append({"role": "user", "content": tool_results})
1264 
1265 return messages
1266 ```
1267 
1268 ```typescript TypeScript
1269 async function samplingLoop(
1270 model: string,
1271 messages: Anthropic.Beta.BetaMessageParam[],
1272 maxIterations = 10,
1273 ): Promise<Anthropic.Beta.BetaMessageParam[]> {
1274 // Run the computer-use agent loop until Claude stops requesting tools
1275 // or the iteration limit is reached.
1276 for (let i = 0; i < maxIterations; i++) {
1277 const response = await client.beta.messages.create({
1278 model,
1279 max_tokens: 4096,
1280 messages,
1281 tools,
1282 betas: ["computer-use-2025-11-24"],
1283 });
1284 
1285 // Add Claude's response to the conversation history
1286 messages.push({ role: "assistant", content: response.content });
1287 
1288 // Run any tools Claude requested and collect results
1289 const toolResults = processToolCalls(response);
1290 if (toolResults.length === 0) {
1291 return messages; // No more tool use; task complete
1292 }
1293 
1294 // Send tool results back to Claude for the next iteration
1295 messages.push({ role: "user", content: toolResults });
1296 }
1297 
1298 return messages;
1299 }
1300 ```
1301 
1302 ```csharp C#
1303 async Task<List<BetaMessageParam>> SamplingLoop(
1304 Model model,
1305 List<BetaMessageParam> messages,
1306 int maxIterations = 10
1307 )
1308 {
1309 // Run the computer-use agent loop until Claude stops requesting tools
1310 // or the iteration limit is reached.
1311 for (var i = 0; i < maxIterations; i++)
1312 {
1313 var response = await client.Beta.Messages.Create(
1314 new MessageCreateParams
1315 {
1316 Model = model,
1317 MaxTokens = 4096,
1318 Messages = messages,
1319 Tools = tools,
1320 Betas = ["computer-use-2025-11-24"],
1321 }
1322 );
1323 
1324 // Add Claude's response to the conversation history
1325 messages.Add(
1326 new()
1327 {
1328 Role = Role.Assistant,
1329 Content = response
1330 .Content.Select(block => new BetaContentBlockParam(block.Json))
1331 .ToList(),
1332 }
1333 );
1334 
1335 // Run any tools Claude requested and collect results
1336 var toolResults = ProcessToolCalls(response);
1337 if (toolResults.Count == 0)
1338 {
1339 return messages; // No more tool use; task complete
1340 }
1341 
1342 // Send tool results back to Claude for the next iteration
1343 messages.Add(new() { Role = Role.User, Content = toolResults });
1344 }
1345 
1346 return messages;
1347 }
1348 ```
1349 
1350 ```go Go
1351 // samplingLoop runs the computer-use agent loop until Claude stops
1352 // requesting tools or the iteration limit is reached.
1353 func samplingLoop(ctx context.Context, model anthropic.Model, messages []anthropic.BetaMessageParam, maxIterations int) ([]anthropic.BetaMessageParam, error) {
1354 for range maxIterations {
1355 response, err := client.Beta.Messages.New(ctx, anthropic.BetaMessageNewParams{
1356 Model: model,
1357 MaxTokens: 4096,
1358 Messages: messages,
1359 Tools: tools,
1360 Betas: []anthropic.AnthropicBeta{"computer-use-2025-11-24"},
1361 })
1362 if err != nil {
1363 return nil, err
1364 }
1365 
1366 // Add Claude's response to the conversation history
1367 messages = append(messages, response.ToParam())
1368 
1369 // Run any tools Claude requested and collect results
1370 toolResults := processToolCalls(response)
1371 if len(toolResults) == 0 {
1372 return messages, nil // No more tool use; task complete
1373 }
1374 
1375 // Send tool results back to Claude for the next iteration
1376 messages = append(messages, anthropic.BetaMessageParam{
1377 Role: anthropic.BetaMessageParamRoleUser,
1378 Content: toolResults,
1379 })
1380 }
1381 return messages, nil
1382 }
1383 
1384 ```
1385 
1386 ```java Java
1387 /**
1388 * Run the computer-use agent loop until Claude stops requesting tools
1389 * or the iteration limit is reached.
1390 */
1391 List<BetaMessageParam> samplingLoop(Model model, List<BetaMessageParam> messages, int maxIterations) {
1392 for (int i = 0; i < maxIterations; i++) {
1393 BetaMessage response = client.beta().messages().create(MessageCreateParams.builder()
1394 .model(model)
1395 .maxTokens(4096)
1396 .messages(messages)
1397 .addTool(COMPUTER_TOOL)
1398 .addBeta("computer-use-2025-11-24")
1399 .build());
1400 
1401 // Add Claude's response to the conversation history
1402 messages.add(BetaMessageParam.builder()
1403 .role(BetaMessageParam.Role.ASSISTANT)
1404 .contentOfBetaContentBlockParams(
1405 response.content().stream().map(BetaContentBlock::toParam).toList())
1406 .build());
1407 
1408 // Run any tools Claude requested and collect results
1409 List<BetaContentBlockParam> toolResults = processToolCalls(response);
1410 if (toolResults.isEmpty()) {
1411 return messages; // No more tool use; task complete
1412 }
1413 
1414 // Send tool results back to Claude for the next iteration
1415 messages.add(BetaMessageParam.builder()
1416 .role(BetaMessageParam.Role.USER)
1417 .contentOfBetaContentBlockParams(toolResults)
1418 .build());
1419 }
1420 return messages;
1421 }
1422 ```
1423 
1424 ```php PHP
1425 /**
1426 * Run the computer-use agent loop until Claude stops requesting tools
1427 * or the iteration limit is reached.
1428 */
1429 function samplingLoop(string $model, array $messages, int $maxIterations = 10): array
1430 {
1431 global $client, $tools;
1432 
1433 for ($i = 0; $i < $maxIterations; $i++) {
1434 $response = $client->beta->messages->create(
1435 model: $model,
1436 maxTokens: 4096,
1437 messages: $messages,
1438 tools: $tools,
1439 betas: ['computer-use-2025-11-24'],
1440 );
1441 
1442 // Add Claude's response to the conversation history
1443 $messages[] = BetaMessageParam::with(role: Role::ASSISTANT, content: $response->content);
1444 
1445 // Run any tools Claude requested and collect results
1446 $toolResults = processToolCalls($response);
1447 if ($toolResults === []) {
1448 return $messages; // No more tool use; task complete
1449 }
1450 
1451 // Send tool results back to Claude for the next iteration
1452 $messages[] = BetaMessageParam::with(role: Role::USER, content: $toolResults);
1453 }
1454 
1455 return $messages;
1456 }
1457 ```
1458 
1459 ```ruby Ruby
1460 # Run the computer-use agent loop until Claude stops requesting tools
1461 # or the iteration limit is reached.
1462 def sampling_loop(model, messages, max_iterations: 10)
1463 max_iterations.times do
1464 response = CLIENT.beta.messages.create(
1465 model: model,
1466 max_tokens: 4096,
1467 messages: messages,
1468 tools: TOOLS,
1469 betas: ["computer-use-2025-11-24"]
1470 )
1471 
1472 # Add Claude's response to the conversation history
1473 messages << {role: "assistant", content: response.content}
1474 
1475 # Run any tools Claude requested and collect results
1476 tool_results = process_tool_calls(response)
1477 return messages if tool_results.empty? # No more tool use; task complete
1478 
1479 # Send tool results back to Claude for the next iteration
1480 messages << {role: "user", content: tool_results}
1481 end
1482 
1483 messages
1484 end
1485 ```
1486 </CodeGroup>
1556 Wrap the two previous steps in a loop that sends the results back and repeats until Claude returns no member tool calls; [Understand the agent loop](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#understanding-the-agentic-loop) shows this loop in each language.
14871557 </Step>
14881558</Steps>
14891559 
1490#### Handle errors
1491 
1492When implementing the computer use tool, various errors might occur. Here's how to handle them:
1493 
1494<AccordionGroup>
1495 <Accordion title="Screenshot capture failure">
1496 If screenshot capture fails, return an appropriate error message:
1497 
1498 ```json
1560### Handle errors
1561 
1562Report a failed action to Claude as a `tool_result` with `is_error: true` and a short description, and include `"toolset_name": "computer"` as on any other member result. If the failed action was part of a [batch action](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#batch-actions), answer the remaining blocks in the batch with the halt text shown there instead of running them.
1563 
1564For example, when screenshot capture fails:
1565 
1566```json
1567{
1568 "role": "user",
1569 "content": [
14991570 {
1500 "role": "user",
1501 "content": [
1502 {
1503 "type": "tool_result",
1504 "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
1505 "content": "Error: Failed to capture screenshot. Display may be locked or unavailable.",
1506 "is_error": true
1507 }
1508 ]
1571 "type": "tool_result",
1572 "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
1573 "toolset_name": "computer",
1574 "content": "Error: Failed to capture screenshot. Display may be locked or unavailable.",
1575 "is_error": true
15091576 }
1510 ```
1511 </Accordion>
1512 
1513 <Accordion title="Invalid coordinates">
1514 If Claude provides coordinates outside the display bounds:
1515 
1516 ```json
1517 {
1518 "role": "user",
1519 "content": [
1520 {
1521 "type": "tool_result",
1522 "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
1523 "content": "Error: Coordinates (1200, 900) are outside display bounds (1024x768).",
1524 "is_error": true
1525 }
1526 ]
1527 }
1528 ```
1529 </Accordion>
1530 
1531 <Accordion title="Action execution failure">
1532 If an action fails to run:
1533 
1534 ```json
1535 {
1536 "role": "user",
1537 "content": [
1538 {
1539 "type": "tool_result",
1540 "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
1541 "content": "Error: Failed to perform click action. The application may be unresponsive.",
1542 "is_error": true
1543 }
1544 ]
1545 }
1546 ```
1547 </Accordion>
1548</AccordionGroup>
1549 
1550#### Size screenshots to fit image limits
1551 
1552Screenshots sent to the computer tool should fit within Claude's image size limits (see [image size limits](https://platform.claude.com/docs/en/build-with-claude/vision#evaluate-image-size)). The API downscales oversized images before Claude sees them, and Claude returns coordinates for the image it sees, so relying on the server-side downscale leaves you without the scale factor you need to map those coordinates back to your screen. Only images over the API's separate [request limits](https://platform.claude.com/docs/en/build-with-claude/vision#request-limits) (for example, more than 8,000 px on a side) are rejected with a validation error rather than downscaled.
1577 ]
1578}
1579```
1580 
1581Use the same shape for coordinates outside the display bounds and for actions that fail to run, with a message that says what went wrong.
1582 
1583### Size screenshots to fit image limits
1584 
1585Screenshots and zoom images that you return to the computer use toolset must already fit within your model's [image size limits](https://platform.claude.com/docs/en/build-with-claude/vision#evaluate-image-size): the toolset takes no display dimensions and the API doesn't downscale for you, so an oversized `tool_result` image is rejected with a validation error. Because Claude returns coordinates in the pixel space of the image it sees, keep the scale factor you used so you can map those coordinates back to your screen.
15531586 
15541587<Note>
1555 Limits vary by model. Claude Opus 5, Claude Sonnet 5, Claude Opus 4.8, and Claude Opus 4.7 accept up to 2576 pixels on the long edge; earlier models accept up to 1568 pixels on the long edge and approximately 1.15 megapixels total. The following example uses the earlier-model 1568 px / 1.15 MP limits; substitute your model's limit.
1588 Limits vary by model. Claude Opus 4.7 and later models, including every model that supports `computer_toolset_20260801`, accept up to 2576 pixels on the long edge and 4784 visual tokens total (`⌈width / 28⌉ × ⌈height / 28⌉`, approximately 3.75 megapixels); earlier models accept up to 1568 pixels on the long edge and approximately 1.15 megapixels total (see [Resolution and token cost](https://platform.claude.com/docs/en/build-with-claude/vision#evaluate-image-size) for each model's tier). The following example uses the earlier-model 1568 px / 1.15 MP limits. For a high-resolution-tier model, size to the visual-token limit rather than a pixel total, for example with the resize helper in [Resize your image before uploading](https://platform.claude.com/docs/en/build-with-claude/vision-coordinates#resize-your-image-before-uploading).
15561589</Note>
15571590 
1558If your screen is larger than the limit, resize the screenshot before sending it, set `display_width_px`/`display_height_px` to the resized dimensions, and scale Claude's returned coordinates back to the original screen space:
1559 
1560<CodeGroup>
1561 ```bash cURL
1562 # Coordinate scaling and screenshot resizing happen in your application code, not
1563 # in the API request. See the SDK tabs for the helper pattern.
1564 ```
1565 
1566 ```bash CLI
1567 # Coordinate scaling and screenshot resizing happen in your application code, not
1568 # in the API request. See the SDK tabs for the helper pattern.
1569 ```
1570 
1591If your screen is larger than the limit, resize each screenshot before returning it and scale Claude's returned coordinates back to the original screen space. Because the toolset takes no display dimensions, the resize and the coordinate scaling in your application code are all you need:
1592 
1593<CodeGroup exclude="shell">
15711594 ```python Python
15721595 import math
1596 
1597 screen_width, screen_height = 1512, 982
15731598 
15741599 
15751600 def get_scale_factor(width, height):
from line 1625
16001625 ```
16011626 
16021627 ```typescript TypeScript
1628 const screenWidth = 1512;
1629 const screenHeight = 982;
16031630 const MAX_LONG_EDGE = 1568;
16041631 const MAX_PIXELS = 1_150_000;
16051632 
from line 1657
16301657 ```
16311658 
16321659 ```csharp C#
1660 int screenWidth = 1512, screenHeight = 982;
1661 
16331662 double GetScaleFactor(int width, int height)
16341663 {
16351664 // Calculate scale factor to meet API constraints.
from line 1696
16671696 }
16681697 
16691698 // ...
1699 screenWidth, screenHeight := 1512, 982
1700 
16701701 // When capturing screenshot
16711702 scale := getScaleFactor(screenWidth, screenHeight)
16721703 scaledWidth := int(float64(screenWidth) * scale)
from line 1724
16931724 }
16941725 
16951726 void main() {
1696 // ...
1727 int screenWidth = 1512, screenHeight = 982;
1728 
16971729 // When capturing screenshot
16981730 double scale = getScaleFactor(screenWidth, screenHeight);
16991731 int scaledWidth = (int)(screenWidth * scale);
from line 1750
17181750 sqrt(1_150_000 / ($width * $height)),
17191751 );
17201752 }
1721 // ...
1753 
1754 $screenWidth = 1512;
1755 $screenHeight = 982;
1756 
17221757 // When capturing screenshot
17231758 $scale = getScaleFactor($screenWidth, $screenHeight);
17241759 $scaledWidth = (int)($screenWidth * $scale);
from line 1770
17351770 def get_scale_factor(width, height)
17361771 [1.0, 1568.0 / [width, height].max, Math.sqrt(1_150_000.0 / (width * height))].min
17371772 end
1738 # ...
1773 
1774 screen_width, screen_height = 1512, 982
1775 
17391776 # When capturing screenshot
17401777 scale = get_scale_factor(screen_width, screen_height)
17411778 scaled_width = (screen_width * scale).to_i
from line 1790
17531790 **macOS Retina displays** capture screenshots at a device pixel ratio of 2, so the image is twice the resolution of the logical screen coordinates. Either downscale the screenshot by 2x before sending, or halve the coordinates Claude returns before issuing the click.
17541791</Note>
17551792 
1756#### Diagnose click issues
1793When you choose a display resolution and return screenshots:
1794 
1795* For general desktop tasks, use 1024x768 or 1280x720; for web applications, use 1280x800 or 1366x768.
1796* Avoid resolutions above 1920x1080 to prevent performance issues.
1797* Encode screenshots as base64 PNG or JPEG, and consider compressing large screenshots to improve performance.
1798* Include relevant metadata such as timestamp or display state.
1799* If you use higher resolutions, ensure coordinates are accurately scaled.
1800 
1801### Manage screenshot history
1802 
1803Long agent loops accumulate screenshots quickly (roughly 1,000–1,800 input tokens each). The API's [request limits](https://platform.claude.com/docs/en/build-with-claude/vision#request-limits) also apply. Once a single request carries more than 20 images, every image in it is held to a stricter per-side limit. A loop that keeps its screenshot history reaches that count within a few dozen turns, so either resize each screenshot so that neither side exceeds 2000 px or prune older screenshots to keep 20 or fewer in the request.
1804 
1805To keep [Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) effective while bounding context:
1806 
1807* Place one `cache_control` breakpoint after the system prompt and tool definitions, and up to three more on the last `tool_result` block of each of the most recent turns, advancing them each turn. Within a [batch action](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#batch-actions), markers on several blocks act as a single breakpoint but each still counts toward the limit of four, so use one per turn.
1808* Prune old screenshots in *batches*, not one each turn. Dropping a screenshot every turn changes the prefix every turn and invalidates the cache. A reasonable default is to keep the last three screenshots and prune every 25 turns, so the prefix stays byte-identical between prune events; if your screenshots exceed 2000 px on either side, choose an interval that keeps each request at 20 or fewer images.
1809 
1810### Diagnose click issues
17571811 
17581812If clicks miss their targets, the cause is usually one of the following:
17591813 
1760| Symptom | Likely cause | Try |
1761| ------------------------------------------------- | --------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
1762| Clicks consistently offset in one direction | `display_width_px`/`display_height_px` don't match the image dimensions actually sent | Ensure display dimensions exactly match the screenshot you send |
1763| Clicks land in the right area but miss the target | Target is very small, detail was lost downscaling a 4K+ source, or aspect ratio was distorted | Set `enable_zoom: true`; capture at lower DPI or crop to the relevant region; preserve aspect ratio when resizing |
1764| Claude clicks the wrong element entirely | Ambiguous instruction, or visually similar elements nearby | Use positional prompts ("the blue Submit button in the bottom-right"); break the interaction into smaller steps |
1765| Accuracy is consistently poor | Resolution too low | Try 1280x720 as a baseline |
1814| Symptom | Likely cause | Try |
1815| ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1816| Clicks consistently offset in one direction | Claude's coordinates, which are in the pixel space of the screenshots you return, are being applied to a display of a different size without scaling | Scale each coordinate by the ratio of your screen size to your screenshot size before clicking (see [Size screenshots to fit image limits](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#handle-coordinate-scaling-for-higher-resolutions)); on macOS Retina displays, account for the 2x device pixel ratio |
1817| Clicks land in the right area but miss the target | Target is very small, detail was lost downscaling a 4K+ source, or aspect ratio was distorted | Keep the `zoom` member enabled and implement it so Claude can inspect the region at full resolution; capture at lower DPI or crop to the relevant region; preserve aspect ratio when resizing |
1818| Claude clicks the wrong element entirely | Ambiguous instruction, or visually similar elements nearby | Use positional prompts ("the blue Submit button in the bottom-right"); break the interaction into smaller steps |
1819| Accuracy is consistently poor | Resolution too low | Try 1280x720 as a baseline |
17661820 
17671821<Tip>
1768 **Model choice affects click precision.** Claude Sonnet 4.6 is more mechanically precise at clicking than Claude Opus 4.6 and is more robust when screenshots require heavy downscaling. Claude Opus 4.7 narrows that gap: its click precision is roughly comparable to Sonnet 4.6, and its higher resolution limit means less downscaling is needed.
1822 **Model choice affects click precision.** Among the models that use the earlier `computer_20251124` tool, Claude Sonnet 4.6 is more mechanically precise at clicking than Claude Opus 4.6 and is more robust when screenshots require heavy downscaling. Claude Opus 4.7 narrows that gap: its click precision is roughly comparable to Sonnet 4.6, and its higher resolution limit means less downscaling is needed.
17691823</Tip>
17701824 
1771#### Follow implementation best practices
1825### Follow implementation best practices
17721826 
17731827<AccordionGroup>
1774 <Accordion title="Use appropriate display resolution">
1775 Set display dimensions that match your use case while staying within recommended limits:
1776 
1777 * For general desktop tasks: 1024x768 or 1280x720
1778 * For web applications: 1280x800 or 1366x768
1779 * Avoid resolutions above 1920x1080 to prevent performance issues
1780 </Accordion>
1781 
1782 <Accordion title="Implement proper screenshot handling">
1783 When returning screenshots to Claude:
1784 
1785 * Encode screenshots as base64 PNG or JPEG
1786 * Consider compressing large screenshots to improve performance
1787 * Include relevant metadata such as timestamp or display state
1788 * If using higher resolutions, ensure coordinates are accurately scaled
1789 
1790 A screenshot goes back as an image content block inside the `tool_result` content array (see [Handle tool calls](https://platform.claude.com/docs/en/agents-and-tools/tool-use/handle-tool-calls)):
1791 
1792 ```json
1793 {
1794 "role": "user",
1795 "content": [
1796 {
1797 "type": "tool_result",
1798 "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
1799 "content": [
1800 {
1801 "type": "image",
1802 "source": {
1803 "type": "base64",
1804 "media_type": "image/png",
1805 "data": "iVBORw0KGgo..."
1806 }
1807 }
1808 ]
1809 }
1810 ]
1811 }
1812 ```
1813 </Accordion>
1814 
1815 <Accordion title="Manage screenshot history for prompt caching">
1816 Long agent loops accumulate screenshots quickly (roughly 1,000–1,800 input tokens each). To keep [Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) effective while bounding context:
1817 
1818 * Place one `cache_control` breakpoint after the system prompt and tool definitions, and up to three more on the most recent `tool_result` blocks, advancing them each turn.
1819 * Prune old screenshots in *batches*, not one each turn. Dropping a screenshot every turn changes the prefix every turn and invalidates the cache. A reasonable default is to keep the last three screenshots and prune every 25 turns, so the prefix stays byte-identical between prune events.
1820 </Accordion>
1821 
18221828 <Accordion title="Add action delays">
18231829 Some applications need time to respond to actions:
18241830 
1825 <CodeGroup>
1826 ```bash cURL
1827 # This is application-side helper code with no API request. See the SDK tabs for
1828 # the pattern.
1829 ```
1830 
1831 ```bash CLI
1832 # This is application-side helper code with no API request. See the SDK tabs for
1833 # the pattern.
1834 ```
1835 
1831 <CodeGroup exclude="shell">
18361832 ```python Python
18371833 def click_and_wait(x, y, wait_time=0.5):
18381834 click_at(x, y)
from line 1892
18961892 <Accordion title="Validate actions before running them">
18971893 Check that requested actions are safe and valid:
18981894 
1899 <CodeGroup>
1900 ```bash cURL
1901 # This is application-side helper code with no API request. See the SDK tabs for
1902 # the pattern.
1903 ```
1904 
1905 ```bash CLI
1906 # This is application-side helper code with no API request. See the SDK tabs for
1907 # the pattern.
1908 ```
1909 
1895 <CodeGroup exclude="shell">
19101896 ```python Python
1897 display_width, display_height = 1024, 768
1898 
1899 
19111900 def validate_action(action_type, params):
1912 if action_type == "left_click":
1913 x, y = params.get("coordinate", (0, 0))
1901 if action_type == "left_click" and "coordinate" in params:
1902 x, y = params["coordinate"]
19141903 if not (0 <= x < display_width and 0 <= y < display_height):
19151904 return False, "Coordinates out of bounds"
19161905 return True, None
19171906 ```
19181907 
19191908 ```typescript TypeScript
1909 const displayWidth = 1024;
1910 const displayHeight = 768;
1911 
19201912 interface ActionParams {
19211913 coordinate?: [number, number];
19221914 }
19231915 
19241916 function validateAction(actionType: string, params: ActionParams): [boolean, string | null] {
1925 if (actionType === "left_click") {
1926 const [x, y] = params.coordinate ?? [0, 0];
1917 if (actionType === "left_click" && params.coordinate) {
1918 const [x, y] = params.coordinate;
19271919 if (!(x >= 0 && x < displayWidth && y >= 0 && y < displayHeight)) {
19281920 return [false, "Coordinates out of bounds"];
19291921 }
from line 1930
19381930 // ...
19391931 static (bool IsValid, string? Error) ValidateAction(string actionType, IReadOnlyDictionary<string, JsonElement> parameters)
19401932 {
1941 if (actionType == "left_click")
1933 if (actionType == "left_click" && parameters.TryGetValue("coordinate", out JsonElement coordinate))
19421934 {
1943 int x = parameters["coordinate"][0].GetInt32();
1944 int y = parameters["coordinate"][1].GetInt32();
1935 int x = coordinate[0].GetInt32();
1936 int y = coordinate[1].GetInt32();
19451937 if (x is < 0 or >= DisplayWidth || y is < 0 or >= DisplayHeight)
19461938 {
19471939 return (false, "Coordinates out of bounds");
from line 1950
19581950 )
19591951 
19601952 func validateAction(actionType string, params map[string]any) (bool, string) {
1961 if actionType == "left_click" {
1962 coord, ok := params["coordinate"].([]any)
1953 raw, hasCoordinate := params["coordinate"]
1954 if actionType == "left_click" && hasCoordinate {
1955 coord, ok := raw.([]any)
19631956 if !ok || len(coord) != 2 {
19641957 return false, "Invalid coordinate"
19651958 }
from line 1972
19791972 record Validation(boolean valid, String error) {}
19801973 
19811974 Validation validateAction(String actionType, Map<String, JsonValue> params) {
1982 if (actionType.equals("left_click")) {
1975 if (actionType.equals("left_click") && params.containsKey("coordinate")) {
19831976 List<JsonValue> coord = (List<JsonValue>) params.get("coordinate").asArray().get();
19841977 long x = ((Number) coord.get(0).asNumber().get()).longValue();
19851978 long y = ((Number) coord.get(1).asNumber().get()).longValue();
from line 1991
19981991 /** @return array{bool, ?string} */
19991992 function validateAction(string $actionType, array $params): array
20001993 {
2001 if ($actionType === 'left_click') {
2002 [$x, $y] = $params['coordinate'] ?? [0, 0];
1994 if ($actionType === 'left_click' && isset($params['coordinate'])) {
1995 [$x, $y] = $params['coordinate'];
20031996 if (!(0 <= $x && $x < DISPLAY_WIDTH && 0 <= $y && $y < DISPLAY_HEIGHT)) {
20041997 return [false, 'Coordinates out of bounds'];
20051998 }
from line 2006
20132006 DISPLAY_HEIGHT = 768
20142007 
20152008 def validate_action(action_type, params)
2016 if action_type == "left_click"
2017 x, y = params.fetch(:coordinate, [0, 0])
2009 if action_type == "left_click" && params.key?(:coordinate)
2010 x, y = params[:coordinate]
20182011 unless (0...DISPLAY_WIDTH).cover?(x) && (0...DISPLAY_HEIGHT).cover?(y)
20192012 return [false, "Coordinates out of bounds"]
20202013 end
from line 2021
20282021 <Accordion title="Log actions for debugging">
20292022 Keep a log of all actions for troubleshooting:
20302023 
2031 <CodeGroup>
2032 ```bash cURL
2033 # This is application-side helper code with no API request. See the SDK tabs for
2034 # the pattern.
2035 ```
2036 
2037 ```bash CLI
2038 # This is application-side helper code with no API request. See the SDK tabs for
2039 # the pattern.
2040 ```
2041 
2024 <CodeGroup exclude="shell">
20422025 ```python Python
20432026 import logging
20442027 
from line 2090
21072090 
21082091***
21092092 
2110## Understand computer use limitations
2111 
2112Computer use is in beta. Keep the following limitations in mind:
2093## Migrate from `computer_20251124`
2094 
2095Upgrading from `computer_20251124` to the toolset is optional: the models listed for `computer_20251124` under [Earlier tool versions](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#earlier-tool-versions) keep accepting it with its beta header, so an existing integration keeps working until you change it. To upgrade, make the following changes together:
2096 
20971. **Remove the beta header.** Drop `anthropic-beta: computer-use-2025-11-24` from your requests. In the SDKs, remove the `betas` parameter and call the Messages API through the standard client rather than the beta namespace.
20982. **Change the `tools` entry.** Set `type` to `computer_toolset_20260801` and delete `name`, `display_width_px`, `display_height_px`, `display_number`, and `enable_zoom`. The toolset rejects each of these fields.
20993. **Choose whether to keep zoom enabled.** Zoom is enabled by default on the toolset, whereas `enable_zoom` defaults to `false`. If your environment doesn't implement zoom, add `"configs": {"zoom": {"enabled": false}}` to keep the previous behavior; otherwise implement it (see [Available actions](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#available-actions)).
21004. **Handle every block in a turn.** Update your agent loop to iterate over every `tool_use` block in a response rather than reading only the first, and to dispatch on the block's `name` together with `toolset_name` instead of on `input.action`. Member inputs no longer contain an `action` field; the remaining fields are unchanged.
21015. **Run blocks in order and use the halt text.** Run the blocks sequentially, stop at the first failure, and answer the remaining blocks with `Not executed: an earlier computer action in this turn failed.` as described in [Batch actions](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#batch-actions). If your loop can't run batches yet, [Tool parameters](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#tool-parameters) explains how to limit Claude to one action per turn.
21026. **Echo `toolset_name` on results.** Add `"toolset_name": "computer"` to every `tool_result` that answers a member call. Results may contain only `text` and `image` content.
21037. **Support `repeat` on `key`.** The `key` member accepts an optional `repeat` count from 1 to 100. A handler that ignores unrecognized fields would press the key once, so make your `key` handler honor `repeat`.
21048. **Resize screenshots yourself.** The toolset rejects a screenshot or zoom image that exceeds the model's image limits instead of downscaling it. Resize before returning the image and keep scaling coordinates as described in [Size screenshots to fit image limits](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#handle-coordinate-scaling-for-higher-resolutions).
21059. **Remove unsupported options.** Move any `defer_loading` from the entry into `configs`, with the same value on every enabled member. The other options not supported on toolset entries are listed under [Client toolsets](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-reference#client-toolsets).
2106 
2107This is the `tools` entry before the change, sent with the `anthropic-beta: computer-use-2025-11-24` header:
2108 
2109```json
2110{
2111 "type": "computer_20251124",
2112 "name": "computer",
2113 "display_width_px": 1024,
2114 "display_height_px": 768,
2115 "display_number": 1
2116}
2117```
2118 
2119This is the `tools` entry after the change, sent with no beta header. The `configs` object keeps zoom off to match the earlier entry, which doesn't set `enable_zoom`; omit `configs` entirely to accept the default and let Claude zoom:
2120 
2121```json
2122{
2123 "type": "computer_toolset_20260801",
2124 "configs": {
2125 "zoom": { "enabled": false }
2126 }
2127}
2128```
2129 
2130The following pair shows a `tool_use` block before and after the change. The action name moves from `input.action` to `name`, and the block gains `toolset_name`:
2131 
2132```json
2133{
2134 "type": "tool_use",
2135 "id": "toolu_01A9r5kQm2LxWc7vT3nZ4bJs",
2136 "name": "computer",
2137 "input": { "action": "left_click", "coordinate": [500, 300] }
2138}
2139```
2140 
2141```json
2142{
2143 "type": "tool_use",
2144 "id": "toolu_01A9r5kQm2LxWc7vT3nZ4bJs",
2145 "name": "left_click",
2146 "toolset_name": "computer",
2147 "input": { "coordinate": [500, 300] }
2148}
2149```
2150 
2151## Earlier tool versions
2152 
2153Two earlier versions of the computer use tool remain available in beta for existing integrations, for models that don't support the toolset, and on platforms where the toolset isn't currently available. Each requires its [beta header](https://platform.claude.com/docs/en/api/beta-headers) on every request, and their parameters are documented in the [beta Messages API reference](https://platform.claude.com/docs/en/api/beta/messages/create). In the SDKs, pass the header through the `betas` parameter and use the beta namespace; only the computer use tool needs the header, not the bash or text editor tools in the same request.
2154 
2155| Tool version | Beta header | Use with | Parameters |
2156| ------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
2157| `computer_20251124` | `computer-use-2025-11-24` | Claude Fable 5, Claude Mythos 5, Claude Opus 5, Claude Sonnet 5, Claude Opus 4.8, Claude Opus 4.7, Claude Opus 4.6, Claude Sonnet 4.6, and Claude Opus 4.5 | [API reference](https://platform.claude.com/docs/en/api/beta/messages/create) |
2158| `computer_20250124` | `computer-use-2025-01-24` | Claude Sonnet 4.5, Claude Haiku 4.5, Claude Opus 4.1 ([retired, except on Bedrock and Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)), Claude Sonnet 4 ([retired, except on Bedrock and Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)), and Claude Opus 4 ([retired, except on Google Cloud](https://platform.claude.com/docs/en/about-claude/model-deprecations)) | [API reference](https://platform.claude.com/docs/en/api/beta/messages/create) |
2159 
2160***
2161 
2162## Limitations
21132163 
211421641. **Latency:** The current computer use latency for human-AI interactions might be too slow compared to regular human-directed computer actions. Focus on use cases where speed isn't critical (for example, background information gathering, automated software testing) in trusted environments.
2115 
21162. **Computer vision accuracy and reliability:** Claude might make mistakes or hallucinate when outputting specific coordinates while generating actions. Extended thinking can help you understand the model's reasoning and identify potential issues.
2117 
21652. **Computer vision accuracy and reliability:** Claude might make mistakes or hallucinate when outputting specific coordinates while generating actions. Claude's [summarized thinking](https://platform.claude.com/docs/en/build-with-claude/thinking#summarized-thinking) output can help you understand the model's reasoning and identify potential issues; set `display: "summarized"` on the thinking configuration, because the models that support the toolset omit thinking text by default.
211821663. **Tool selection accuracy and reliability:** Claude might make mistakes or hallucinate when selecting tools while generating actions or take unexpected actions to solve problems. Additionally, reliability might be lower when interacting with niche applications or multiple applications at once. Prompt the model carefully when requesting complex tasks.
2119 
212021674. **Scrolling reliability:** The scroll action supports direction control (up, down, left, right) and a specified amount. In applications where scrolling doesn't take effect, keyboard alternatives such as Page Down can help.
2121 
212221685. **Spreadsheet interaction:** Use the fine-grained mouse control actions (`left_mouse_down`, `left_mouse_up`) and modifier-key combinations to select individual cells. Complex spreadsheet operations might still require multiple attempts.
2123 
21246. **Account creation and content generation on social and communications platforms:** While Claude will visit websites, Claude's ability to create accounts or generate and share content or otherwise engage in human impersonation across social media websites and platforms is limited. This capability might be updated in the future.
2125 
21267. **Vulnerabilities:** Vulnerabilities such as jailbreaking or prompt injection might persist across frontier AI systems, including the beta computer use API. In some circumstances, Claude will follow commands found in content, sometimes even when they conflict with your instructions. For example, instructions on webpages or contained in images might override your instructions or cause Claude to make mistakes. Consider the following:
2127 
2128 * Limiting computer use to trusted environments such as virtual machines or containers with minimal privileges
2129 * Avoiding giving computer use access to sensitive accounts or data without strict oversight
2130 * Informing end users of relevant risks and obtaining their consent before enabling or requesting permissions necessary for computer use features in your applications
2131 
21696. **Account creation and content generation on social and communications platforms:** Although Claude visits websites, its ability to create accounts, generate and share content, or otherwise engage in human impersonation across social media websites and platforms is limited.
21707. **Vulnerabilities:** Jailbreaks and prompt injection can affect computer use as they can any frontier AI system, including through instructions embedded in webpages or images; apply the precautions in [Security considerations](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#security-considerations).
213221718. **Inappropriate or illegal actions:** Under Anthropic's Terms of Service, you must not employ computer use to violate any laws or the Acceptable Use Policy.
21332172 
21342173Always carefully review and verify Claude's computer use actions and logs. Do not use Claude for tasks requiring perfect precision or sensitive user information without human oversight.
from line 2182
21432182 
21442183Computer use follows the standard [tool use pricing](https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview#pricing). When using the computer use tool:
21452184 
2146**System prompt overhead:** The computer use beta adds 466–499 tokens to the system prompt
2147 
2148**Computer use tool token usage:**
2149 
2150| Model | Input tokens per tool definition |
2151| ----------------- | -------------------------------- |
2152| Claude 4.x models | 735 tokens |
2185**Toolset definition overhead:** Declaring `computer_toolset_20260801` with its default members adds about 4,500 input tokens to a request (about 4,520 on Claude Fable 5, Claude Mythos 5, Claude Opus 5, and Claude Opus 4.8, and about 4,590 on Claude Sonnet 5), which covers the member tool definitions and the tool use system prompt. Disabling `zoom` with `configs` removes about 410 of those tokens. The exact count for a request is reported in the response `usage`, and you can estimate it in advance with the [token counting endpoint](https://platform.claude.com/docs/en/build-with-claude/token-counting).
2186 
2187**Earlier tool versions:** The following figures apply to the `computer_20251124` and `computer_20250124` tool versions, not to `computer_toolset_20260801`:
2188 
2189* System prompt overhead: 466–499 tokens added to the system prompt
2190* Tool definition: about 735 input tokens per tool definition (measured with `computer_20250124`)
21532191 
21542192**Additional token consumption:**
21552193 
2156* Screenshot images (see [Vision pricing](https://platform.claude.com/docs/en/build-with-claude/vision))
2194* Screenshot and zoom images returned in tool results, billed as image input (see [Vision pricing](https://platform.claude.com/docs/en/build-with-claude/vision#evaluate-image-size))
21572195* Tool execution results returned to Claude
21582196 
21592197<Note>
from line 2216
21782216 <Card title="Best practices in detail" icon="book" href="https://claude.com/blog/best-practices-for-computer-and-browser-use-with-claude">
21792217 Benchmarked recommendations for resolution, thinking effort, and context management
21802218 </Card>
2219 
2220 <Card title="Browser use tool" icon="browser" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/browser-use-tool">
2221 Let Claude navigate, read, and interact with webpages in your own browser environment, for tasks that stay inside the browser.
2222 </Card>
21812223</CardGroup>
21822224 
Feedback