---
title: 브라우저 사용 도구
url: https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool
description: 브라우저 사용 도구를 사용하여 Claude가 자체 브라우저 환경에서 웹페이지를 탐색하고, 읽고, 상호작용하도록 하세요.
featureMetadata:
  status: ga
  zdr:
    eligibility: eligible
    note: Excludes [Covered Models](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention#model-specific-data-retention-requirements).
  supportedModels:
    - claude-fable-5-1
    - claude-mythos-5-1
    - claude-fable-5
    - claude-mythos-5
    - claude-opus-5-5
    - claude-opus-5
    - claude-sonnet-5-5
    - claude-sonnet-5
    - claude-opus-4-8
    - claude-haiku-5-5
  supportedPlatforms:
    Claude API: ga
    Google Cloud: ga
---

<Note>
  **SDK 도구 세트로 시작하세요:** Python 및 TypeScript SDK에는 베타 버전의 브라우저 도구 세트 클래스가 있습니다. [파트너 통합](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-sdk#partner-integrations)에서 시작하거나 [SDK 도구 세트를 사용한 브라우저 및 컴퓨터 사용](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-sdk)을 참조하세요. 이 페이지는 도구 레퍼런스로 사용하거나, 도구 호출을 직접 처리할 때 사용하세요.
</Note>

브라우저 사용 도구를 사용하면 Claude가 애플리케이션이 실행하는 브라우저에서 웹페이지를 탐색하고, 읽고, 상호작용할 수 있습니다. Claude는 페이지의 구조("accessibility tree"(접근성 트리), 요소, 양식, 탭)와 스크린샷 및 "viewport"(뷰포트) 좌표를 모두 활용하여 페이지를 다룹니다.

이 도구는 Anthropic이 정의한 ["client toolset"(클라이언트 도구 세트)](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/tool-reference#client-toolsets)입니다. `tools`에 `browser_toolset_20260801` 항목 하나를 추가하면 Claude는 기본적으로 `navigate`, `read_page`, `left_click`, `screenshot` 등 27개의 "member tool"(멤버 도구)을 사용할 수 있으며, [활성화하면](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#enable-optional-member-tools) 4개가 더 추가됩니다. 애플리케이션은 모든 호출을 자체 브라우저 자동화에서 실행하며, Anthropic 측에서는 아무것도 실행되지 않습니다. 이 도구는 현재 [Claude Managed Agents](https://platform.claude.com/docs/ko/managed-agents/tools)에서 사용할 수 없습니다.

작업이 웹페이지 안에서 이루어지고 페이지에 대한 조작이 필요한 경우, 또는 페이지가 JavaScript로 콘텐츠를 구성하는 경우 브라우저 사용을 선택하세요. 작업에 데스크톱 전체가 필요한 경우에는 스크린샷과 좌표만으로 작동하는 [컴퓨터 사용 도구](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/computer-use-tool)를 사용하세요. Claude에게 알려줄 수 있는 페이지를 읽거나 웹에서 출처를 찾는 경우에는 [웹 가져오기 도구](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/web-fetch-tool)와 [웹 검색 도구](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/web-search-tool)가 더 가볍습니다. 이들은 API가 대신 실행하는 [서버 도구](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/server-tools)이며, 조작할 브라우저가 필요하지 않습니다.

브라우저 사용에서 Claude는 실제 웹페이지를 읽고 그에 대해 동작하므로, 페이지가 제공하는 모든 것은 신뢰할 수 없는 입력이며 Claude가 취하는 동작은 실제 영향을 미칠 수 있습니다. 배포하기 전에 [보안 고려 사항](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#security-considerations)을 참조하세요.

## 빠른 시작

브라우저 사용 도구는 Claude API와 [Google Cloud](https://platform.claude.com/docs/ko/build-with-claude/claude-on-vertex-ai)에서 사용할 수 있습니다. [Messages API](https://platform.claude.com/docs/ko/api/messages/create) 요청의 `tools` 배열에 `name` 없이 `browser_toolset_20260801` 유형의 항목 하나를 추가하세요.

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "content-type: application/json" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 2048,
      "tools": [
        {
          "type": "browser_toolset_20260801"
        }
      ],
      "messages": [
        {
          "role": "user",
          "content": "Open example.com/docs and tell me how to get started."
        }
      ]
    }'
  ```

  ```bash CLI
  ant messages create <<'YAML'
  model: claude-opus-5-5
  max_tokens: 2048
  tools:
    - type: browser_toolset_20260801
  messages:
    - role: user
      content: Open example.com/docs and tell me how to get started.
  YAML
  ```

  ```python Python
  client = anthropic.Anthropic()

  response = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=2048,
      tools=[{"type": "browser_toolset_20260801"}],
      messages=[
          {
              "role": "user",
              "content": "Open example.com/docs and tell me how to get started.",
          }
      ],
  )
  print(response)
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const response = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 2048,
    tools: [{ type: "browser_toolset_20260801" }],
    messages: [
      {
        role: "user",
        content: "Open example.com/docs and tell me how to get started."
      }
    ]
  });

  console.log(response);
  ```

  ```csharp C#
  var client = new AnthropicClient();

  var parameters = new MessageCreateParams
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 2048,
      Tools = [new BrowserToolset20260801()],
      Messages =
      [
          new MessageParam
          {
              Role = Role.User,
              Content = "Open example.com/docs and tell me how to get started.",
          },
      ],
  };

  var response = await client.Messages.Create(parameters);
  Console.WriteLine(response);
  ```

  ```go Go
  client := anthropic.NewClient()

  response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 2048,
  	Tools: []anthropic.ToolUnionParam{
  		{OfBrowserToolset20260801: &anthropic.BrowserToolset20260801Param{}},
  	},
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Open example.com/docs and tell me how to get started.")),
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }
  fmt.Println(response.RawJSON())
  ```

  ```java Java
  import com.anthropic.models.messages.BrowserToolset20260801;
  // ...

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(2048L)
          .addTool(BrowserToolset20260801.builder().build())
          .addUserMessage("Open example.com/docs and tell me how to get started.")
          .build();

      Message response = client.messages().create(params);
      IO.println(response);
  }
  ```

  ```php PHP
  $client = new Client();

  $response = $client->messages->create(
      maxTokens: 2048,
      messages: [
          ['role' => 'user', 'content' => 'Open example.com/docs and tell me how to get started.'],
      ],
      model: 'claude-opus-5-5',
      tools: [
          ['type' => 'browser_toolset_20260801'],
      ],
  );

  echo $response;
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  response = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 2048,
    tools: [
      { type: "browser_toolset_20260801" }
    ],
    messages: [
      {
        role: "user",
        content: "Open example.com/docs and tell me how to get started."
      }
    ]
  )

  puts response
  ```
</CodeGroup>

Claude의 첫 번째 응답은 `stop_reason: "tool_use"`로 끝나며 하나 이상의 멤버 `tool_use` 블록을 포함합니다. 각 블록은 `name`에 멤버 도구 이름을 지정하고 `"toolset_name": "browser"`를 포함합니다:

```json Output
{
  "id": "msg_01HCDu4XSTLzTAcodEQ58vDo",
  "type": "message",
  "role": "assistant",
  "model": "claude-opus-5-5",
  "content": [
    {
      "type": "text",
      "text": "I'll open the documentation and read the page to find the getting-started instructions."
    },
    {
      "type": "tool_use",
      "id": "toolu_01NRLabsLyVHZPKxbKvkfSMn",
      "name": "navigate",
      "toolset_name": "browser",
      "input": { "url": "https://example.com/docs" }
    },
    {
      "type": "tool_use",
      "id": "toolu_01UvHU5cDyTZ2vXKf5wCkPqR",
      "name": "read_page",
      "toolset_name": "browser",
      "input": { "filter": "interactive" }
    }
  ],
  "stop_reason": "tool_use",
  "stop_sequence": null
}
```

"Executor"(실행기), 즉 브라우저를 구동하고 도구 결과를 생성하는 애플리케이션 부분은 `navigate`를 실행한 다음 `read_page`를 실행합니다. 애플리케이션은 다음 요청에서 블록마다 하나의 `tool_result`를 반환하며, 각 결과에 `toolset_name`을 그대로 포함합니다. `navigate` 결과는 로드된 탭을 `browser_state` 블록으로 보고하고, `read_page` 결과는 모든 요소에 참조가 붙은 텍스트입니다:

```json
{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_01NRLabsLyVHZPKxbKvkfSMn",
      "toolset_name": "browser",
      "content": [
        { "type": "text", "text": "Navigated to https://example.com/docs" },
        {
          "type": "browser_state",
          "tabs": [
            {
              "tab_id": "tab-1",
              "title": "Documentation",
              "url": "https://example.com/docs",
              "active": true
            }
          ]
        }
      ]
    },
    {
      "type": "tool_result",
      "tool_use_id": "toolu_01UvHU5cDyTZ2vXKf5wCkPqR",
      "toolset_name": "browser",
      "content": [
        {
          "type": "text",
          "text": "link \"Documentation\" [ref_1]\nlink \"Getting started\" [ref_2]\ntextbox \"Search docs\" [ref_3]\nbutton \"Search\" [ref_4]\nlink \"Pricing\" [ref_5]"
        }
      ]
    }
  ]
}
```

이제 Claude는 동작에 사용할 수 있는 참조를 보유하므로, 다음 턴에서 스크린샷에서 링크를 먼저 찾을 필요 없이 `ref_2`를 클릭하여 시작하기 페이지를 열 수 있습니다.

## 브라우저 사용의 작동 방식

브라우저 사용은 애플리케이션에서 "agent loop"(에이전트 루프)로 실행됩니다. Claude가 멤버 도구 호출을 반환하면 실행기가 이를 브라우저에서 실행하고, Claude가 텍스트로 답변할 때까지 결과를 반환합니다.

<Steps>
  <Step title="Claude에게 브라우저 사용 도구와 사용자 프롬프트 제공">
    * API 요청에 `browser_toolset_20260801` 항목과 선택적으로 다른 도구를 추가합니다.
    * 웹페이지 작업이 필요한 사용자 프롬프트를 포함합니다. 예: "example.com/docs를 열고 시작하는 방법을 알려주세요."
  </Step>

  <Step title="Claude가 멤버 도구 호출로 응답">
    * Claude는 하나의 어시스턴트 턴에서 하나 이상의 `tool_use` 블록을 반환합니다. 한 턴에 여러 개가 있으면 배치 동작이 됩니다. 예: `left_click`, 그다음 `type`, 그다음 `key`.
    * 각 블록의 `name`은 멤버 이름이고, 각 블록은 `"toolset_name": "browser"`를 포함하며, `input`에는 `action` 필드 없이 해당 멤버의 매개변수만 들어 있습니다. 응답의 `stop_reason`은 `tool_use`입니다.
  </Step>

  <Step title="호출을 순서대로 실행하고 결과 반환">
    * `response.content`의 모든 `tool_use` 블록을 순회하고(정확히 하나만 있다고 가정하지 마세요), 나중 호출은 대개 이전 호출에 의존하므로 나타난 순서대로 순차적으로 실행합니다.
    * 새 `user` 메시지에서 블록마다 하나의 `tool_result`를 `tool_use_id`로 매칭하여 반환하고, 각각에 `"toolset_name": "browser"`를 그대로 포함합니다. 모든 호출에 응답해야 하며, 그렇지 않으면 다음 요청이 거부됩니다.
    * 호출이 실패하면 해당 블록에 대해 텍스트 설명과 함께 `is_error: true`를 반환한 다음, 해당 턴의 이후 모든 블록에 [배치 동작](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#batch-actions)의 중단 규칙을 적용합니다.
  </Step>

  <Step title="작업이 완료될 때까지 Claude가 계속 진행">
    * Claude는 결과(페이지 텍스트, 접근성 트리, 스크린샷, 탭 상태)를 읽고, 더 필요하면 추가 멤버 호출을 반환하며, 이 경우 3단계로 돌아갑니다.
    * 그렇지 않으면 사용자에게 텍스트 응답을 반환합니다.
  </Step>
</Steps>

다음은 해당 루프의 도구 호출 단계를 두 부분으로 나눈 골격입니다. 먼저, 스텁 멤버 핸들러가 여러분의 브라우저 자동화를 대신합니다. 다섯 개의 멤버(`navigate`, `read_page`, `left_click`, `type`, `screenshot`)는 결과 콘텐츠가 되는 텍스트를, `screenshot`의 경우 이미지 블록을 반환하며, 디스패처는 구현하지 않은 멤버에 대해 오류를 발생시킵니다.

<CodeGroup exclude="shell">
  ```python Python
  # 플레이스홀더 이미지 데이터; 실제 실행기는 뷰포트를 캡처하여 PNG 바이트를 반환합니다
  PLACEHOLDER_PNG = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="


  def navigate(url):
      return f"navigated to {url}"


  def read_page():
      return 'link "Docs" [ref_1]\nbutton "Search" [ref_2]'


  def click(target):
      # 대상은 read_page 또는 find의 요소 참조이거나 뷰포트 좌표입니다
      if target["type"] == "ref":
          return f"clicked {target['ref']}"
      return f"clicked at ({target['x']}, {target['y']})"


  def type_text(text):
      return f"typed: {text}"


  def capture_screenshot() -> list[ImageBlockParam]:
      # screenshot은 텍스트 대신 이미지 블록으로 응답합니다: 결과 콘텐츠 목록을 반환합니다
      return [
          {
              "type": "image",
              "source": {
                  "type": "base64",
                  "media_type": "image/png",
                  "data": PLACEHOLDER_PNG,
              },
          }
      ]


  def handle_browser_action(name, tool_input):
      if name == "navigate":
          return navigate(tool_input["url"])
      elif name == "read_page":
          return read_page()
      elif name == "left_click":
          return click(tool_input["target"])
      elif name == "type":
          return type_text(tool_input["text"])
      elif name == "screenshot":
          return capture_screenshot()
      # 필요에 따라 다른 액션을 처리합니다
      raise ValueError(f"Unknown or unimplemented member: {name}")
  ```

  ```typescript TypeScript
  // 플레이스홀더 이미지 데이터; 실제 실행기는 뷰포트를 PNG 바이트로 캡처합니다
  const PLACEHOLDER_PNG =
    "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==";

  function navigate(url: string): string {
    return `navigated to ${url}`;
  }

  function readPage(): string {
    return 'link "Docs" [ref_1]\nbutton "Search" [ref_2]';
  }

  function clickElement(ref: string): string {
    return `clicked ${ref}`;
  }

  function clickAt(x: number, y: number): string {
    return `clicked at (${x}, ${y})`;
  }

  function typeText(text: string): string {
    return `typed: ${text}`;
  }

  function captureScreenshot(): Anthropic.ImageBlockParam[] {
    // screenshot은 텍스트 대신 이미지 블록으로 응답합니다
    return [
      {
        type: "image",
        source: {
          type: "base64",
          media_type: "image/png",
          data: PLACEHOLDER_PNG
        }
      }
    ];
  }

  function handleBrowserAction(
    action: string,
    input: unknown
  ): string | Anthropic.ImageBlockParam[] {
    const params: object = typeof input === "object" && input !== null ? input : {};
    if (action === "navigate" && "url" in params) {
      return navigate(String(params.url));
    } else if (action === "read_page") {
      return readPage();
    } else if (action === "left_click" && "target" in params) {
      // target은 read_page의 요소 참조 또는 뷰포트 좌표입니다
      const target: object =
        typeof params.target === "object" && params.target !== null ? params.target : {};
      if ("type" in target && target.type === "ref" && "ref" in target) {
        return clickElement(String(target.ref));
      } else if ("x" in target && "y" in target) {
        return clickAt(Number(target.x), Number(target.y));
      }
    } else if (action === "type" && "text" in params) {
      return typeText(String(params.text));
    } else if (action === "screenshot") {
      return captureScreenshot();
    }
    // 필요에 따라 다른 액션을 처리합니다
    throw new Error(`Unknown or unimplemented member: ${action}`);
  }
  ```

  ```csharp C#
  // 자리표시자 이미지 데이터; 실제 실행기는 뷰포트를 캡처하여 PNG 바이트를 반환합니다
  const string PlaceholderPng = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==";

  string Navigate(string url) => $"navigated to {url}";

  string ReadPage() =>
      """
      link "Docs" [ref_1]
      button "Search" [ref_2]
      """;

  string ClickRef(string elementRef) => $"clicked {elementRef}";

  string ClickAt(int x, int y) => $"clicked at ({x}, {y})";

  // target은 {"type": "ref", "ref": "ref_1"} 또는 {"type": "coordinate", "x": 640, "y": 380} 형식입니다
  string Click(JsonElement target) =>
      target.GetProperty("type").GetString() == "ref"
          ? ClickRef(target.GetProperty("ref").GetString()!)
          : ClickAt(target.GetProperty("x").GetInt32(), target.GetProperty("y").GetInt32());

  string TypeText(string text) => $"typed: {text}";

  // screenshot은 텍스트 대신 이미지 블록으로 응답합니다: 결과 콘텐츠 목록을 반환합니다
  List<Block> CaptureScreenshot() =>
      [
          new ImageBlockParam(
              new Base64ImageSource { Data = PlaceholderPng, MediaType = MediaType.ImagePng }
          ),
      ];

  ToolResultBlockParamContent HandleBrowserAction(
      string action,
      IReadOnlyDictionary<string, JsonElement> input
  ) =>
      action switch
      {
          "navigate" => Navigate(input["url"].GetString()!),
          "read_page" => ReadPage(),
          "left_click" => Click(input["target"]),
          "type" => TypeText(input["text"].GetString()!),
          "screenshot" => CaptureScreenshot(),
          // 필요에 따라 다른 액션을 처리합니다
          _ => throw new NotSupportedException($"Unknown or unimplemented member: {action}"),
      };
  ```

  ```go Go
  // placeholderPNG는 실제 캡처를 대신합니다. 실행기는
  // 뷰포트를 base64로 인코딩된 PNG 데이터로 반환합니다.
  const placeholderPNG = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="

  // textContent는 텍스트를 tool_result 콘텐츠로 감쌉니다.
  func textContent(text string) []anthropic.ToolResultBlockParamContentUnion {
  	return []anthropic.ToolResultBlockParamContentUnion{
  		{OfText: &anthropic.TextBlockParam{Text: text}},
  	}
  }

  func navigate(url string) string {
  	return fmt.Sprintf("navigated to %s", url)
  }

  func readPage() string {
  	return "link \"Docs\" [ref_1]\nbutton \"Search\" [ref_2]"
  }

  func clickRef(ref string) string {
  	return fmt.Sprintf("clicked %s", ref)
  }

  func clickAt(x, y int) string {
  	return fmt.Sprintf("clicked at (%d, %d)", x, y)
  }

  func typeText(text string) string {
  	return fmt.Sprintf("typed: %s", text)
  }

  // captureScreenshot은 텍스트 대신 이미지 블록을 반환합니다.
  func captureScreenshot() []anthropic.ToolResultBlockParamContentUnion {
  	return []anthropic.ToolResultBlockParamContentUnion{{
  		OfImage: &anthropic.ImageBlockParam{
  			Source: anthropic.ImageBlockParamSourceUnion{
  				OfBase64: &anthropic.Base64ImageSourceParam{
  					MediaType: anthropic.Base64ImageSourceMediaTypeImagePNG,
  					Data:      placeholderPNG,
  				},
  			},
  		},
  	}}
  }

  func handleBrowserAction(action string, params map[string]any) ([]anthropic.ToolResultBlockParamContentUnion, error) {
  	switch action {
  	case "navigate":
  		if url, ok := params["url"].(string); ok {
  			return textContent(navigate(url)), nil
  		}
  	case "read_page":
  		return textContent(readPage()), nil
  	case "left_click":
  		// target은 read_page의 요소 참조이거나 뷰포트 좌표입니다
  		target, _ := params["target"].(map[string]any)
  		if ref, ok := target["ref"].(string); ok && target["type"] == "ref" {
  			return textContent(clickRef(ref)), nil
  		}
  		x, xok := target["x"].(float64)
  		y, yok := target["y"].(float64)
  		if xok && yok {
  			return textContent(clickAt(int(x), int(y))), nil
  		}
  	case "type":
  		if text, ok := params["text"].(string); ok {
  			return textContent(typeText(text)), nil
  		}
  	case "screenshot":
  		return captureScreenshot(), nil
  	// 필요에 따라 다른 액션을 처리합니다
  	default:
  		return nil, fmt.Errorf("unknown or unimplemented member: %s", action)
  	}
  	// 멤버의 입력에 필드가 누락되었거나 필드 타입이 잘못된 경우 도달합니다
  	return nil, fmt.Errorf("invalid input for %s", action)
  }
  ```

  ```java Java
  /** Placeholder pixels; a real executor captures the viewport and base64-encodes the PNG. */
  static final String PLACEHOLDER_PNG = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==";

  ToolResultBlockParam.Content captureScreenshot() {
      ImageBlockParam image = ImageBlockParam.builder()
              .source(Base64ImageSource.builder()
                      .mediaType(Base64ImageSource.MediaType.IMAGE_PNG)
                      .data(PLACEHOLDER_PNG)
                      .build())
              .build();
      return ToolResultBlockParam.Content.ofBlocks(
              List.of(ToolResultBlockParam.Content.Block.ofImage(image)));
  }

  String navigate(String url) {
      return "navigated to " + url;
  }

  String readPage() {
      return """
              link "Docs" [ref_1]
              button "Search" [ref_2]""";
  }

  String clickRef(String ref) {
      return "clicked " + ref;
  }

  String clickAt(long x, long y) {
      return "clicked at (" + x + ", " + y + ")";
  }

  String typeText(String text) {
      return "typed: " + text;
  }

  /** Runs one browser toolset member; {@code action} is the tool_use block's name. */
  ToolResultBlockParam.Content handleBrowserAction(String action, Map<String, JsonValue> input) {
      if (action.equals("screenshot")) {
          return captureScreenshot(); // the one member here that answers with an image block
      }
      String output = switch (action) {
          case "navigate" -> navigate(input.get("url").asStringOrThrow());
          case "read_page" -> readPage();
          case "left_click" -> {
              // target은 {"type": "ref", "ref": "ref_1"} 또는 {"type": "coordinate", "x": 640, "y": 380} 형식입니다
              Map<String, JsonValue> target =
                      (Map<String, JsonValue>) input.get("target").asObject().get();
              if (target.get("type").asStringOrThrow().equals("ref")) {
                  yield clickRef(target.get("ref").asStringOrThrow());
              }
              long x = ((Number) target.get("x").asNumber().get()).longValue();
              long y = ((Number) target.get("y").asNumber().get()).longValue();
              yield clickAt(x, y);
          }
          case "type" -> typeText(input.get("text").asStringOrThrow());
          // 필요에 따라 다른 액션을 처리합니다
          default -> throw new UnsupportedOperationException("Unknown or unimplemented member: " + action);
      };
      return ToolResultBlockParam.Content.ofString(output);
  }
  ```

  ```php PHP
  // 실제 PNG 바이트의 대체물입니다. 실제 실행기는 뷰포트를 캡처합니다
  const PLACEHOLDER_PNG = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==';

  function navigateTo(string $url): string
  {
      return "navigated to {$url}";
  }

  function readPage(): string
  {
      return <<<'TEXT'
          link "Docs" [ref_1]
          button "Search" [ref_2]
          TEXT;
  }

  function clickTarget(array $target): string
  {
      // target은 read_page 또는 find의 요소 참조이거나 뷰포트 픽셀 좌표입니다
      if ($target['type'] === 'ref') {
          return "clicked {$target['ref']}";
      }

      return "clicked at ({$target['x']}, {$target['y']})";
  }

  function typeText(string $text): string
  {
      return "typed: {$text}";
  }

  function captureScreenshot(): array
  {
      // screenshot은 텍스트가 아닌 이미지 블록으로 응답하므로 결과 콘텐츠 목록을 반환합니다
      $image = [
          'type' => 'image',
          'source' => ['type' => 'base64', 'media_type' => 'image/png', 'data' => PLACEHOLDER_PNG],
      ];

      return [$image];
  }

  function handleBrowserAction(string $name, array $input): string|array
  {
      return match ($name) {
          'navigate' => navigateTo($input['url']),
          'read_page' => readPage(),
          'left_click' => clickTarget($input['target']),
          'type' => typeText($input['text']),
          'screenshot' => captureScreenshot(),
          // 필요에 따라 다른 액션을 처리합니다
          default => throw new \RuntimeException("Unknown or unimplemented member: {$name}"),
      };
  }
  ```

  ```ruby Ruby
  # 대체용 이미지 데이터입니다. 실제 실행기는 뷰포트를 PNG로 캡처합니다.
  PLACEHOLDER_PNG = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="

  def navigate(url)
    "navigated to #{url}"
  end

  def read_page
    <<~TREE
      link "Docs" [ref_1]
      button "Search" [ref_2]
    TREE
  end

  def click(target)
    return "clicked #{target[:ref]}" if target[:type] == "ref"

    "clicked at (#{target[:x]}, #{target[:y]})"
  end

  def type_text(text)
    "typed: #{text}"
  end

  def capture_screenshot
    [
      {
        type: "image",
        source: { type: "base64", media_type: "image/png", data: PLACEHOLDER_PNG }
      }
    ]
  end

  def handle_browser_action(name, input)
    case name
    when "navigate"
      navigate(input[:url])
    when "read_page"
      read_page
    when "left_click"
      # target은 요소 참조(read_page 또는 find에서 가져옴) 또는 좌표입니다
      click(input[:target])
    when "type"
      type_text(input[:text])
    when "screenshot"
      capture_screenshot
    # 필요에 따라 다른 액션을 처리합니다
    else
      raise ArgumentError, "Unknown or unimplemented member: #{name}"
    end
  end
  ```
</CodeGroup>

두 번째 부분은 배치를 순서대로 실행하고, 각 블록을 해당 핸들러로 디스패치하며, 모든 결과에 `toolset_name`을 그대로 되돌려 주고, [배치 동작](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#batch-actions)의 중단 규칙을 적용하여 핸들러 오류를 오류 결과로 바꿉니다. 이를 호출하는 샘플링 루프는 [에이전트 루프 이해하기](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/computer-use-tool#understanding-the-agentic-loop)에 나온 것과 같으며, `tools`에 브라우저 도구 세트가 들어 있습니다.

<CodeGroup exclude="shell">
  ```python Python
  NOT_EXECUTED = "Not executed: an earlier action in this turn failed."


  def process_tool_calls(response: Message) -> list[ToolResultBlockParam]:
      """
      Run the browser actions in Claude's response in order and answer each
      one. After the first failure the rest are skipped, because Claude planned
      them assuming the earlier actions succeeded.
      """
      tool_results: list[ToolResultBlockParam] = []
      failed = False
      for block in response.content:
          # 브라우저 도구 세트만 선언되어 있습니다; 다른 도구를 추가하는 경우 여기로 라우팅하세요
          if block.type != "tool_use" or block.toolset_name != "browser":
              continue
          result: ToolResultBlockParam = {
              "type": "tool_result",
              "tool_use_id": block.id,
              "toolset_name": "browser",
          }
          if failed:
              result["content"] = NOT_EXECUTED
              result["is_error"] = True
          else:
              try:
                  # 문자열 또는 콘텐츠 블록 목록; 실제 실행기는 또한
                  # 탐색 및 탭 관리 결과에 browser_state 블록을 추가합니다
                  result["content"] = handle_browser_action(block.name, block.input)
              except Exception as err:
                  result["content"] = f"Error: {err}"
                  result["is_error"] = True
                  failed = True
          tool_results.append(result)
      return tool_results
  ```

  ```typescript TypeScript
  const HALT_TEXT = "Not executed: an earlier action in this turn failed.";

  function browserResult(
    toolUseId: string,
    content: string | Anthropic.ImageBlockParam[],
    isError?: boolean
  ): Anthropic.ToolResultBlockParam {
    return {
      type: "tool_result",
      tool_use_id: toolUseId,
      toolset_name: "browser",
      content,
      is_error: isError
    };
  }

  function processToolCalls(response: Anthropic.Message): Anthropic.ToolResultBlockParam[] {
    const toolResults: Anthropic.ToolResultBlockParam[] = [];
    let failed = false;
    for (const block of response.content) {
      if (block.type !== "tool_use") {
        continue;
      }
      if (block.toolset_name !== "browser") {
        // 이 예제는 브라우저 도구 세트만 선언합니다; 다른 도구를 추가하는 경우
        // 여기서 라우팅하세요.
        continue;
      }
      if (failed) {
        // 배치는 첫 번째 실패에서 중단됩니다; 이후 액션은 미실행으로 응답합니다
        toolResults.push(browserResult(block.id, HALT_TEXT, true));
        continue;
      }
      try {
        // 문자열 또는 이미지 블록 목록; 실제 실행기는 탐색 및 탭 관리 결과에
        // browser_state 블록도 추가합니다
        const result = handleBrowserAction(block.name, block.input);
        toolResults.push(browserResult(block.id, result));
      } catch (error) {
        failed = true;
        const message = error instanceof Error ? error.message : String(error);
        toolResults.push(browserResult(block.id, `Error: ${message}`, true));
      }
    }
    return toolResults;
  }
  ```

  ```csharp C#
  const string HaltText = "Not executed: an earlier action in this turn failed.";

  List<ContentBlockParam> ProcessToolCalls(Message response)
  {
      List<ContentBlockParam> toolResults = [];
      var failed = false;
      foreach (var block in response.Content)
      {
          if (!block.TryPickToolUse(out var toolUse))
          {
              continue;
          }

          if (toolUse.ToolsetName != "browser")
          {
              // 이 예제는 브라우저 도구 세트만 선언합니다; 다른 도구를 추가하는 경우
              // 여기서 라우팅하세요.
              continue;
          }

          if (failed)
          {
              // 배치는 첫 번째 실패 시 중단됩니다; 이후 액션은 실행하지 않고 응답합니다
              toolResults.Add(
                  new ToolResultBlockParam(toolUse.ID)
                  {
                      Content = HaltText,
                      IsError = true,
                      ToolsetName = "browser",
                  }
              );
              continue;
          }

          try
          {
              // 문자열 또는 콘텐츠 블록 목록; 실제 실행기는 탐색 및 탭 관리 결과에
              // browser_state 블록도 추가합니다
              var result = HandleBrowserAction(toolUse.Name, toolUse.Input);
              toolResults.Add(
                  new ToolResultBlockParam(toolUse.ID) { Content = result, ToolsetName = "browser" }
              );
          }
          catch (Exception e)
          {
              failed = true;
              toolResults.Add(
                  new ToolResultBlockParam(toolUse.ID)
                  {
                      Content = $"Error: {e.Message}",
                      IsError = true,
                      ToolsetName = "browser",
                  }
              );
          }
      }
      return toolResults;
  }
  ```

  ```go Go
  const notExecuted = "Not executed: an earlier action in this turn failed."

  // browserToolResult는 하나의 브라우저 액션에 대한 결과를 생성합니다.
  // 일반 도구 결과와 달리 툴셋 이름을 그대로 반환해야 합니다. 실제 실행기는 또한
  // 탐색 및 탭 관리 결과에 browser_state 블록을 추가합니다.
  func browserToolResult(toolUseID string, content []anthropic.ToolResultBlockParamContentUnion, isError bool) anthropic.ContentBlockParamUnion {
  	result := anthropic.ToolResultBlockParam{
  		ToolUseID:   toolUseID,
  		ToolsetName: anthropic.String("browser"),
  		Content:     content,
  	}
  	if isError {
  		result.IsError = anthropic.Bool(true)
  	}
  	return anthropic.ContentBlockParamUnion{OfToolResult: &result}
  }

  // processToolCalls는 Claude 응답의 브라우저 액션을 순서대로 실행하고
  // tool_use 블록마다 하나의 tool_result를 생성합니다. 첫 실패 이후에는 나머지를 건너뜁니다.
  // Claude는 이전 액션이 성공했다고 가정하고 이를 계획했기 때문입니다.
  func processToolCalls(response *anthropic.Message) []anthropic.ContentBlockParamUnion {
  	var toolResults []anthropic.ContentBlockParamUnion
  	failed := false
  	for _, block := range response.Content {
  		switch variant := block.AsAny().(type) {
  		case anthropic.ToolUseBlock:
  			// 이 예제는 브라우저 툴셋만 선언합니다. 다른 도구를 추가하면 여기서 라우팅하세요.
  			if variant.ToolsetName != "browser" {
  				continue
  			}
  			if failed {
  				toolResults = append(toolResults, browserToolResult(variant.ID, textContent(notExecuted), true))
  				continue
  			}
  			var input map[string]any
  			var content []anthropic.ToolResultBlockParamContentUnion
  			err := json.Unmarshal(variant.Input, &input)
  			if err == nil {
  				content, err = handleBrowserAction(variant.Name, input)
  			}
  			if err != nil {
  				failed = true
  				content = textContent("Error: " + err.Error())
  			}
  			toolResults = append(toolResults, browserToolResult(variant.ID, content, err != nil))
  		}
  	}
  	return toolResults
  }
  ```

  ```java Java
  /** The exact text the toolset contract prescribes for member calls skipped after a failure. */
  static final String HALT_TEXT = "Not executed: an earlier action in this turn failed.";

  /** Every result answering a browser toolset member echoes toolset_name. */
  ToolResultBlockParam.Builder browserResult(ToolUseBlock toolUse) {
      return ToolResultBlockParam.builder()
              .toolUseId(toolUse.id())
              .toolsetName("browser");
  }

  /**
   * Run the browser actions in Claude's response in order and build one
   * tool_result per tool_use block. After the first failure, skip the rest:
   * Claude planned them assuming the earlier actions succeeded.
   */
  List<ContentBlockParam> processToolCalls(Message response) {
      List<ContentBlockParam> toolResults = new ArrayList<>();
      boolean failed = false;
      for (ContentBlock block : response.content()) {
          // 이 예제는 브라우저 도구 세트만 선언합니다. 다른 도구를 추가하는 경우 여기서 라우팅하세요.
          if (!block.isToolUse() || !block.asToolUse().toolsetName().equals(Optional.of("browser"))) {
              continue;
          }
          ToolUseBlock toolUse = block.asToolUse();
          ToolResultBlockParam result;
          if (failed) {
              result = browserResult(toolUse).content(HALT_TEXT).isError(true).build();
          } else {
              try {
                  Map<String, JsonValue> input =
                          (Map<String, JsonValue>) toolUse._input().asObject().get();
                  ToolResultBlockParam.Content output = handleBrowserAction(toolUse.name(), input);
                  // 실제 실행기는 탐색 및 탭 관리 결과에 browser_state 블록도 추가합니다.
                  // 이 페이지의 "browser_state로 탭 추적하기"를 참조하세요.
                  result = browserResult(toolUse).content(output).build();
              } catch (RuntimeException e) {
                  failed = true;
                  result = browserResult(toolUse).content("Error: " + e.getMessage()).isError(true).build();
              }
          }
          toolResults.add(ContentBlockParam.ofToolResult(result));
      }
      return toolResults;
  }
  ```

  ```php PHP
  const HALT_TEXT = 'Not executed: an earlier action in this turn failed.';

  function processToolCalls(Message $response): array
  {
      $toolResults = [];
      $failed = false;
      foreach ($response->content as $block) {
          // 이 예제는 브라우저 도구 세트만 선언합니다. 다른 도구를 추가하는 경우 여기서 라우팅하세요.
          if (!($block instanceof \Anthropic\Messages\ToolUseBlock) || $block->toolsetName !== 'browser') {
              continue;
          }
          $result = ['type' => 'tool_result', 'tool_use_id' => $block->id, 'toolset_name' => 'browser'];
          if ($failed) {
              // 배치는 첫 번째 실패에서 중단되며, 나머지 액션은 실행되지 않고 응답됩니다
              $toolResults[] = [...$result, 'content' => HALT_TEXT, 'is_error' => true];
              continue;
          }
          try {
              // 실제 실행기는 탐색 및 탭 관리 결과에 browser_state 블록도 반환합니다
              $toolResults[] = [...$result, 'content' => handleBrowserAction($block->name, $block->input)];
          } catch (\Throwable $e) {
              $failed = true;
              $toolResults[] = [...$result, 'content' => 'Error: ' . $e->getMessage(), 'is_error' => true];
          }
      }

      return $toolResults;
  }
  ```

  ```ruby Ruby
  NOT_EXECUTED = "Not executed: an earlier action in this turn failed."

  # Claude 응답의 브라우저 액션을 순서대로 실행하고
  # tool_use 블록마다 tool_result를 하나씩 생성합니다. 첫 실패 이후 나머지는 건너뜁니다.
  # Claude는 이전 액션이 성공했다고 가정하고 계획했기 때문입니다.
  def process_tool_calls(response)
    tool_results = []
    failed = false
    response.content.each do |block|
      # 이 예제는 브라우저 도구 세트만 선언합니다. 다른 도구를 추가하는 경우
      # 여기서 라우팅하세요.
      next unless block.type == :tool_use && block.toolset_name == "browser"

      result = { type: "tool_result", tool_use_id: block.id, toolset_name: "browser" }
      if failed
        result.update(content: NOT_EXECUTED, is_error: true)
      else
        begin
          # String 또는 스크린샷용 콘텐츠 블록입니다. 실제 실행기는 탐색 및
          # 탭 관리 결과에 browser_state 블록도 추가합니다.
          result[:content] = handle_browser_action(block.name, block.input)
        rescue => e
          result.update(content: "Error: #{e.message}", is_error: true)
          failed = true
        end
      end
      tool_results << result
    end
    tool_results
  end
  ```
</CodeGroup>

각 블록을 `name`만이 아니라 (`toolset_name`, `name`) 쌍으로 디스패치하세요. 같은 요청의 커스텀 도구가 멤버의 이름을 공유할 수 있기 때문입니다. [클라이언트 도구 세트](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/tool-reference#client-toolsets)는 두 도구 세트가 공유하는 이 계약의 부분을 설명합니다. Claude가 여러분의 실행기가 구현하지 않은 멤버나 여러분이 비활성화한 멤버를 지정하면, 해당 블록을 버리지 말고 [오류 결과](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#return-errors-from-your-executor)로 응답하세요.

응답을 스트리밍할 때 각 멤버의 `input`은 조각이 아니라 하나의 완전한 `input_json_delta`로 도착하므로, 배치를 실행하기 전에 턴이 끝날 때까지 기다리세요.

### 배치 동작

여러 멤버 호출이 있는 턴은 배치 동작입니다. 호출을 나타나는 순서대로 실행하고, 첫 번째 실패에서 멈추고, 모든 이후 호출에 `is_error: true`와 정확히 `Not executed: an earlier action in this turn failed.`라는 텍스트로 응답하세요. 배치는 [병렬 도구 사용](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/parallel-tool-use)과 같은 응답 형태를 사용합니다. 차이점은 블록을 동시에가 아니라 순서대로 실행한다는 것입니다. 여기서 Claude는 앞서 찾은 검색 상자를 클릭하고, 쿼리를 입력하고, Enter를 한 턴에 누릅니다:

```json
{
  "role": "assistant",
  "content": [
    {
      "type": "tool_use",
      "id": "toolu_01D7FLrfh4GYq7yT1ULFeyMV",
      "name": "left_click",
      "toolset_name": "browser",
      "input": { "target": { "type": "ref", "ref": "ref_3" } }
    },
    {
      "type": "tool_use",
      "id": "toolu_01Ez4kLb1nQ2vXo8sJ9pWm3c",
      "name": "type",
      "toolset_name": "browser",
      "input": { "text": "install" }
    },
    {
      "type": "tool_use",
      "id": "toolu_01FkP8rTz6uYh2mNq4LsXw7v",
      "name": "key",
      "toolset_name": "browser",
      "input": { "text": "Enter" }
    }
  ]
}
```

여러분의 애플리케이션은 하나의 `user` 메시지에 세 개의 `tool_result` 블록을 반환하며, 각각 `toolset_name`과 `Clicked element ref_3.` 같은 짧은 텍스트 확인을 담고 있습니다. Enter를 누르면 결과 페이지가 로드되므로, `key` 결과는 탭의 업데이트된 URL이 담긴 `browser_state` 블록도 담고 있습니다([다른 결과의 탭 컨텍스트](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#tab-context-on-other-results)). 대신 클릭이 실패했다면, 그 결과는 여러분의 오류 텍스트를 담고 나머지 두 결과는 [실행기에서 오류 반환](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#return-errors-from-your-executor)에 나온 것처럼 중단 텍스트를 담게 됩니다.

모든 호출 후에 스크린샷을 반환할 필요는 없습니다. Claude는 보통 관찰 호출(`screenshot`, `read_page`, 또는 `get_page_text`)로 배치를 끝내며, 여러분의 애플리케이션도 왕복을 절약하기 위해 새 스크린샷이나 접근성 트리 같은 자체 관찰을 배치의 마지막 결과에 추가 콘텐츠 블록으로 첨부할 수 있습니다. 탭 관리 결과는 정확히 하나의 `browser_state` 블록이어야 하므로, 탭 관리 호출이 아닌 마지막 결과에 첨부하세요.

여러분의 실행기가 왕복당 하나의 호출만 실행할 수 있다면, `tool_choice`에서 `disable_parallel_tool_use`를 `true`로 설정하세요. 그러면 Claude는 더 많은 왕복을 대가로 턴당 최대 하나의 멤버 호출을 반환합니다([병렬 도구 사용 비활성화](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/parallel-tool-use#disable-parallel-tool-use)). [컴퓨터 사용 도구의 배치 동작](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/computer-use-tool#batch-actions)에 있는 나머지 계약은 다음 `user` 메시지에서 모든 `tool_use`에 대해 하나의 `tool_result`를 반환하는 것을 포함하여 그대로 적용되지만, 두 가지는 예외입니다. 중단 텍스트와 성공한 결과의 `content`가 담는 내용입니다. 결과 콘텐츠는 대신 이 페이지의 [멤버 도구](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#member-tools)를 따릅니다. `new_tab`, `switch_tab`, `close_tab`, 또는 `list_tabs` 결과는 텍스트나 이미지 없이 정확히 하나의 `browser_state` 블록이며([탭 관리 결과](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#tab-management-results)), 다른 멤버의 결과는 텍스트나 이미지에 `browser_state` 블록을 추가할 수 있습니다([다른 결과의 탭 컨텍스트](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#tab-context-on-other-results)). 배치 내부의 캐시 중단점이 어디에서 효력을 발휘하는지는 컴퓨터 사용 도구의 [도구 매개변수](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/computer-use-tool#tool-parameters)의 `cache_control` 행에 설명되어 있습니다.

### 대상과 좌표

위치에 대해 동작하는 멤버 도구는 `target` 객체를 받으며, 이는 뷰포트 픽셀 좌표이거나 `read_page` 또는 `find`가 반환한 요소에 대한 참조입니다. [멤버 도구](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#member-tools) 표에서는 두 형태 중 어느 것이든 받는 매개변수를 `Target`으로 표기합니다.

| 형태                 | `target.type`  | 필드                         | 허용하는 멤버                                                                                                                                                                                 |
| ------------------ | -------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CoordinateTarget` | `"coordinate"` | `x`, `y` (정수, 뷰포트 픽셀)      | `left_click`, `right_click`, `middle_click`, `double_click`, `triple_click`, `hover`, `left_click_drag` (`from` 및 `target`), `left_mouse_down`, `left_mouse_up`, `mouse_move`, `scroll` |
| `RefTarget`        | `"ref"`        | `ref` (`"ref_2"` 같은 요소 참조) | `left_click`, `right_click`, `middle_click`, `double_click`, `triple_click`, `hover`, `scroll_to`, `form_input`, `file_upload`                                                          |

**좌표는 뷰포트 픽셀입니다.** 즉, 렌더링된 페이지의 왼쪽 위를 원점으로 하는 전체 뷰포트 `screenshot`의 픽셀 공간이며, 주변 데스크톱이나 창 프레임은 없습니다. 도구 세트는 디스플레이 크기를 선언하지 않으며 Claude는 여러분이 반환하는 스크린샷에서 뷰포트 크기를 추론하므로, 스크린샷을 일관된 하나의 크기로 유지하세요. `zoom`은 프레임을 바꾸지 않으므로, 그 `region`과 Claude가 확대된 이미지를 본 후 내보내는 모든 좌표는 여전히 전체 뷰포트 픽셀입니다.

**스크린샷은 이미지 제한에 맞아야 합니다.** API는 도구 세트 이미지를 축소하지 않습니다. 모델의 [이미지 크기 제한](https://platform.claude.com/docs/ko/build-with-claude/vision#evaluate-image-size)을 초과하거나, 요청이 [20개를 넘는 이미지](https://platform.claude.com/docs/ko/build-with-claude/vision#request-limits)를 담게 되면 적용되는 더 엄격한 이미지당 제한을 초과하는 스크린샷이나 확대 이미지는 거부됩니다. 반환하기 전에 크기를 조정하고, 디스패치하기 전에 Claude의 좌표를 여러분의 배율의 역수로 다시 확대하세요([이미지 제한에 맞게 스크린샷 크기 조정](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/computer-use-tool#handle-coordinate-scaling-for-higher-resolutions)).

**요소 참조는 `read_page`와 `find`에서 나옵니다.** 빠른 시작 결과에서처럼 출력의 각 요소는 `[ref_2]` 같은 태그를 담고 있습니다:

```text wrap
link "Documentation" [ref_1]
link "Getting started" [ref_2]
textbox "Search docs" [ref_3]
button "Search" [ref_4]
link "Pricing" [ref_5]
```

Claude는 이후의 클릭, `hover`, `scroll_to`, `form_input`, 또는 `file_upload` 호출에서 참조를 `{"type": "ref", "ref": "ref_2"}` 대상으로 되돌려 전달하거나, 하위 트리를 읽기 위해 `read_page`의 `ref` 매개변수로 전달합니다. 여러분의 실행기는 참조를 할당하고, 각 참조에서 기반 노드(접근성 노드 ID, 저장된 선택자, 또는 이에 상응하는 것)로의 매핑을 유지하며, 참조가 돌아오면 해당 노드에 대해 동작합니다.

참조는 이를 생성한 탭으로 범위가 한정되며 해당 탭이 탐색하거나 DOM이 실질적으로 변경될 때까지 유효합니다. API는 오래되었거나 알 수 없는 참조를 감지할 수 없으므로, Claude가 여러분의 실행기가 더 이상 인식하지 못하는 참조를 전달하면 `Error: ref_3 is stale or not found on the current page. Re-read the page to get fresh references.` 같은 오류 결과를 반환하세요. 그러면 Claude는 페이지를 다시 읽습니다. 탭에 대해 이미 건네준 참조는 탭이 탐색할 때까지 번호를 다시 매기지 마세요. 그렇게 하면 Claude가 아직 보유한 참조가 조용히 무효화되기 때문입니다.

Claude는 두 가지 대상 지정 방식을 모두 사용하며 페이지가 노출하는 것에 따라 둘 사이를 전환합니다. 여러분의 프롬프트와 실행기가 반환하는 것이 선택을 이끕니다:

* **페이지에 사용 가능한 접근성 트리가 있는 곳에서는 참조를 선호하세요.** 참조는 픽셀 좌표를 취약하게 만드는 레이아웃 이동과 리플로우를 견디며, 포인터로 맞추기 어려운 컨트롤에 대해 Claude가 동작할 수 있게 합니다.
* **트리가 설명하지 않는 콘텐츠에는 좌표로 대체하세요.** 캔버스로 렌더링된 인터페이스, 임베드된 비디오나 원격 데스크톱 표면, 심하게 가상화된 목록, 교차 출처 iframe 내부의 요소는 유용한 노드가 없는 경우가 많으므로, Claude는 `screenshot`과 `zoom`으로 작업하고 좌표로 클릭합니다. 좌표가 어느 프레임에 떨어지는지는 여러분의 실행기가 해석합니다.
* **읽기 범위를 한정하고, 스크린샷 전에 트리를 읽으세요.** 큰 페이지에서 `filter: "interactive"`나 컨테이너의 `ref`를 사용한 `read_page`는 집중된 하위 트리를 반환하며, 일반적인 페이지의 트리 읽기는 스크린샷보다 입력 토큰이 적게 드는 경우가 많으면서도 Claude가 즉시 동작할 수 있는 참조를 제공합니다. 시각적 레이아웃, 이미지, 또는 렌더링 상태가 중요할 때는 스크린샷이 여전히 올바른 관찰입니다.

## 보안 고려 사항

브라우저 사용은 표준 API 기능에는 없는 위험을 수반합니다. Claude가 공개 웹의 콘텐츠를 읽고 그에 대해 동작하며, 그곳의 어떤 페이지든 Claude를 조종하기 위해 작성된 텍스트를 담고 있을 수 있기 때문입니다.

<Warning>
  이러한 위험을 줄이려면 다음과 같은 예방 조치를 취하세요:

  1. 최소 권한, 자격 증명이 없는 새 프로필, 민감한 파일 시스템이나 내부 네트워크에 대한 접근 권한이 없는 전용 컨테이너 또는 가상 머신에서 브라우저와 실행기를 실행하세요. 함께 실행하는 모든 도구도 같은 방식으로 격리하세요.
  2. 브라우저가 접근할 수 있는 호스트를 네트워크 계층에서 적용되고 리디렉션 후 `navigate` 핸들러에서 다시 확인되는 "domain allowlist"(도메인 허용 목록)로 제한하고, 작업에 필요하지 않은 한 루프백, 링크 로컬 및 사설 범위를 차단하세요.
  3. [`browser_state`](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#track-tabs-and-page-state) 블록에서 보고하는 탭 제목과 URL, 각 다운로드의 `url`, `path`, `error`를 포함하여 페이지가 제공하는 모든 것을 신뢰할 수 없는 입력으로 취급하세요. 또한 숨겨진 텍스트가 Claude에 도달하지 않도록, 원시 DOM 소스가 아닌 페이지가 렌더링하는 내용(접근성 트리 또는 보이는 텍스트)으로 페이지 읽기 결과를 구성하세요.
  4. `navigate` 핸들러에서 기록 키워드 `"back"`, `"forward"`, `"reload"`를 허용하고, 스킴이 없는 URL은 `https://`로 취급한 다음, URL을 파싱하여 `http` 또는 `https` 이외의 모든 스킴(`javascript:`, `file:`, `data:`, `chrome:` 등)을 [오류 결과](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#return-errors-from-your-executor)로 거부하세요. 문자열 접두사가 아닌 URL 파서로 스킴을 확인하세요. API는 Claude가 여는 URL을 필터링하지 않으므로 대신 거부해 줄 수 없습니다.
  5. 필요하지 않다면 `javascript_exec`와 `file_upload`를 비활성화된 상태로 두고, 둘 중 하나를 켜기 전에 [선택적 멤버 활성화](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#enable-optional-member-tools)를 읽어 보세요.
  6. 중대한 결과를 초래하는 작업과 명시적 동의가 필요한 모든 작업(구매, 계정 수정, 메시지 전송, 약관 동의)은 사람이 확인하도록 하고, 한 턴에 여러 호출이 포함될 수 있으므로 각 호출 전에 실행기에서 이 확인을 수행하세요.
</Warning>

Claude는 때때로 페이지 콘텐츠에서 발견한 지시가 여러분의 지시와 충돌하더라도 이를 따릅니다. "이전 지시를 무시하고 ...로 이동하라"는 페이지의 텍스트가 Claude를 작업에서 벗어나게 할 수 있습니다. 프롬프트 인젝션이 도달할 수 있는 범위를 제한하기 위해 Claude를 민감한 데이터와 동작으로부터 격리하고, [탈옥 및 프롬프트 인젝션 완화](https://platform.claude.com/docs/ko/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks)를 검토하고, 작업이 로그인된 세션을 피할 수 없다면 전용 저권한 계정을 사용하고 계정을 변경하는 동작에 대해 사람의 확인을 유지하세요.

Anthropic은 이러한 프롬프트 인젝션에 저항하도록 모델을 학습시켰으며 추가 방어 계층을 더했습니다. 브라우저 사용 도구를 사용하면 분류기가 페이지 텍스트나 스크린샷 등 브라우저가 반환하는 내용을 자동으로 검사하여 잠재적인 프롬프트 인젝션을 표시합니다. 이러한 분류기가 잠재적인 프롬프트 인젝션을 식별하면, 모델이 해당 지시에 따라 행동하기 전에 그 지시가 실제로 사용자에게서 온 것인지 확인하도록 자동으로 유도합니다.

이 추가 보호 기능이 모든 사용 사례(예: 사람이 개입하지 않는 사용 사례)에 이상적이지는 않으므로, 이를 해제하고 끄려면 [지원팀에 문의](https://support.claude.com/en/)하세요. 이러한 분류기가 있더라도 위의 예방 조치는 여전히 중요합니다.

브라우저가 여러분의 환경에서 실행되므로, Claude가 방문하는 사이트는 여러분의 실행기의 네트워크 신원을 보게 되며, 페이지 콘텐츠는 여러분이 반환하는 도구 결과로만 API에 도달합니다. 제품에서 브라우저 사용을 활성화하기 전에 최종 사용자에게 관련 위험을 알리고 동의를 얻으세요.

## 멤버 도구

`browser_toolset_20260801` 항목은 31개의 멤버 도구를 선언합니다. 각 호출의 `input`은 정확히 여기에 나열된 매개변수이며, `tab_id`는 선택적인 경우 활성 탭이 기본값입니다. `Target`, `CoordinateTarget`, `RefTarget`은 [대상과 좌표](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#targets-and-coordinates)에 설명된 형태입니다. 네 개의 멤버(`javascript_exec`, `file_upload`, `read_console`, `read_network`)는 기본적으로 비활성화되어 있으며 [활성화할](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#enable-optional-member-tools) 때만 나타납니다. 각 멤버의 행에 적힌 입력 범위와 출력 규칙은 Claude에게 명시되는 것이지 API가 강제하는 것이 아니므로, 여러분의 실행기에서 입력(뷰포트에 대한 좌표 포함)을 검증하고 규칙을 적용하세요.

`screenshot`과 `zoom`만 결과에 [`image` 블록](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/handle-tool-calls#handling-results-from-client-tools)을 요구하며, 네 개의 탭 관리 멤버(`new_tab`, `list_tabs`, `switch_tab`, `close_tab`)는 정확히 하나의 `browser_state` 블록을 반환합니다([탭 관리 결과](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#tab-management-results) 참조). 다른 모든 멤버는 `text` 블록을 반환합니다. `Clicked element ref_2.` 같은 짧은 확인이거나 멤버의 출력입니다. 탭 관리 결과 이외의 모든 결과는 `image` 블록도 담을 수 있으며, 보통 동작 후에 찍은 스크린샷이어서 Claude가 별도의 `screenshot` 호출 없이 결과를 볼 수 있습니다. [배치 동작](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#batch-actions)은 배치에서 어디에 첨부할지 보여줍니다. 멤버 `tool_result`는 `text`, `image`, `browser_state` 콘텐츠 블록만 담을 수 있습니다.

### 탐색 및 캡처

| 멤버           | 입력                  | 설명                                                                                                                                                                                               |
| ------------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `navigate`   | `url`, `tab_id?`    | `http` 또는 `https` URL을 로드하거나, `"back"`, `"forward"`, 또는 `"reload"`로 히스토리를 이동합니다. 스킴이 없는 URL은 `https://`로 취급하고 다른 스킴은 오류 결과로 거부하세요. 짧은 확인을 반환하고, 탭의 URL이나 제목이 변경되었을 때는 `browser_state` 블록도 반환하세요. |
| `screenshot` | `tab_id?`           | 뷰포트를 캡처하고 `image` 블록을 반환합니다.                                                                                                                                                                     |
| `zoom`       | `region`, `tab_id?` | 작은 텍스트나 컨트롤을 더 자세히 살펴보기 위해, 뷰포트 픽셀로 `[x0, y0, x1, y1]`로 주어진 `region`을 잘라내고 확대한 `image`를 반환합니다.                                                                                                   |

### 포인터

| 멤버                | 입력                                                                          | 설명                                                                                                                               |
| ----------------- | --------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `left_click`      | `target: Target`, `modifiers?`, `tab_id?`                                   | 좌표나 참조된 요소를 왼쪽 클릭합니다. `modifiers`는 클릭 중에 누르고 있는 조합 키입니다. 예: `"shift"` 또는 `"ctrl+shift"`.                                         |
| `right_click`     | `target: Target`, `modifiers?`, `tab_id?`                                   | 좌표나 요소를 오른쪽 클릭합니다.                                                                                                               |
| `middle_click`    | `target: Target`, `modifiers?`, `tab_id?`                                   | 좌표나 요소를 가운데 클릭합니다.                                                                                                               |
| `double_click`    | `target: Target`, `modifiers?`, `tab_id?`                                   | 좌표나 요소를 왼쪽 더블 클릭합니다.                                                                                                             |
| `triple_click`    | `target: Target`, `modifiers?`, `tab_id?`                                   | 좌표나 요소를 왼쪽 트리플 클릭하며, 보통 한 줄이나 단락을 선택합니다.                                                                                         |
| `hover`           | `target: Target`, `tab_id?`                                                 | 클릭하지 않고 좌표나 요소 위로 포인터를 이동합니다.                                                                                                    |
| `left_click_drag` | `from: CoordinateTarget`, `target: CoordinateTarget`, `tab_id?`             | `from`에서 누르고, `target`까지 드래그하고, 놓습니다.                                                                                            |
| `left_mouse_down` | `target: CoordinateTarget`, `tab_id?`                                       | 좌표에서 왼쪽 버튼을 누르고 유지합니다. 커스텀 드래그를 위해 `left_mouse_up`과 짝을 이루세요.                                                                     |
| `left_mouse_up`   | `target: CoordinateTarget`, `tab_id?`                                       | 좌표에서 왼쪽 버튼을 놓습니다.                                                                                                                |
| `mouse_move`      | `target: CoordinateTarget`, `tab_id?`                                       | 포인터를 좌표로 이동합니다.                                                                                                                  |
| `scroll`          | `target: CoordinateTarget`, `scroll_direction`, `scroll_amount?`, `tab_id?` | 뷰포트 위치에서 스크롤합니다. `scroll_direction`은 `"up"`, `"down"`, `"left"`, 또는 `"right"`이고, `scroll_amount`는 스크롤 휠 눈금 단위로 1에서 10, 기본값 3입니다. |
| `scroll_to`       | `target: RefTarget`, `tab_id?`                                              | 참조된 요소를 보이도록 스크롤합니다.                                                                                                             |

### 키보드 및 타이밍

| 멤버         | 입력                            | 설명                                                                                                                                          |
| ---------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `type`     | `text`, `tab_id?`             | 현재 포커스에 리터럴 문자열을 입력합니다.                                                                                                                     |
| `key`      | `text`, `repeat?`, `tab_id?`  | 키나 조합 키를 누릅니다. `text`는 단일 키(`"Enter"`), `+`로 연결된 조합 키(`"ctrl+a"`), 또는 공백으로 구분된 시퀀스(`"Backspace Backspace"`)이고, `repeat`는 1에서 100, 기본값 1입니다. |
| `hold_key` | `text`, `duration`, `tab_id?` | 키나 조합 키를 `duration`초 동안 누르고 있습니다. 0에서 30.                                                                                                   |
| `wait`     | `duration`, `tab_id?`         | `duration`초 동안 일시 정지합니다. 0에서 30.                                                                                                            |

### 페이지 읽기

| 멤버              | 입력                                     | 설명                                                                                                                                                                                                                                                                                              |
| --------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `read_page`     | `filter?`, `depth?`, `ref?`, `tab_id?` | 각 요소에 `[ref_2]` 같은 참조가 태그된 텍스트로 페이지의 접근성 트리를 반환합니다. `filter`를 생략하면 보이는 모든 요소를 반환하고, `"interactive"`이면 보이는 상호작용 요소만, `"all"`이면 뷰포트 밖의 요소도 반환합니다. `depth`는 트리 깊이를 제한하고(최소 1, 기본값 15) `ref`는 읽기를 해당 요소의 하위 트리로 한정합니다. 출력을 50,000자로 제한하고 텍스트에 그렇게 명시하세요. 그러면 Claude는 더 작은 `depth`나 `ref`로 범위를 좁힙니다. |
| `find`          | `query`, `tab_id?`                     | `"search field"`나 `"add to cart button"` 같은 자연어 설명과 일치하는 요소를 검색하고, `read_page`와 같은 태그 형식으로 최대 20개의 일치 항목을 반환합니다.                                                                                                                                                                                |
| `get_page_text` | `tab_id?`                              | 주요 기사 콘텐츠를 우선하여 페이지의 보이는 텍스트를 일반 텍스트로 반환합니다. 기사, 문서, 기타 텍스트 중심 페이지에 적합합니다.                                                                                                                                                                                                                      |

### 폼 및 파일

| 멤버                         | 입력                                                        | 설명                                                                                                                                                                                                                |
| -------------------------- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `form_input`               | `target: RefTarget`, `value`, `tab_id?`                   | 폼 요소의 값을 직접 설정합니다. `value`는 `string`, `number`, 또는 `boolean`이며, 체크박스에는 `boolean`을, 셀렉트에는 옵션의 값이나 보이는 텍스트를 사용하세요.                                                                                                  |
| `file_upload` (기본적으로 비활성화) | `target: RefTarget`, `paths?`, `document_ids?`, `tab_id?` | 실행기 파일 시스템의 `paths`, 여러분의 애플리케이션이 준비한 `document_ids`, 또는 둘 다로부터 파일 입력 요소의 파일을 설정합니다. 적어도 하나는 필수입니다. [파일 업로드](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#upload-files)를 참조하세요. |

### 진단 및 스크립팅

| 멤버                             | 입력                | 설명                                                                                                                                                                                                |
| ------------------------------ | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `read_console` (기본적으로 비활성화)    | `tab_id?`         | 마지막 읽기 이후 누적된 탭의 콘솔 항목(로그, 경고, 오류 줄)을 항목당 한 줄로 반환합니다. [콘솔 및 네트워크 활동 읽기](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#read-console-and-network-activity)를 참조하세요. |
| `read_network` (기본적으로 비활성화)    | `tab_id?`         | 마지막 읽기 이후 탭의 네트워크 요청(메서드, URL, 상태, MIME 타입, 타이밍)을 항목당 한 줄로 반환합니다.                                                                                                                                 |
| `javascript_exec` (기본적으로 비활성화) | `text`, `tab_id?` | `text`를 페이지 컨텍스트에서 JavaScript로 실행하고 마지막 표현식의 값을 텍스트로 반환합니다. [선택적 멤버 활성화](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#enable-optional-member-tools)를 참조하세요.     |

### 탭 관리

| 멤버           | 입력            | 설명                     |
| ------------ | ------------- | ---------------------- |
| `new_tab`    | (없음)          | 탭을 열고 활성 탭으로 만듭니다.     |
| `list_tabs`  | (없음)          | 탭 목록을 보고합니다.           |
| `switch_tab` | `tab_id` (필수) | `tab_id`를 활성 탭으로 만듭니다. |
| `close_tab`  | `tab_id` (필수) | `tab_id`를 닫습니다.        |

성공 시 이들 각각은 텍스트나 이미지 없이 정확히 하나의 `browser_state` 블록을 반환합니다. [탭 관리 결과](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#tab-management-results)를 참조하세요.

## 도구 세트 구성

`type` 외에 도구 세트 항목은 `configs`, `cache_control`, `allowed_callers`를 받습니다. 이 필드들이 컴퓨터 사용 도구 세트와 공유하는 규칙은 [클라이언트 도구 세트](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/tool-reference#client-toolsets)에 나열되어 있으며, 이 섹션은 브라우저 고유의 기본값을 다룹니다. `configs`는 멤버 이름을 키로 하는 객체이며, 각 멤버의 값은 두 개의 필드를 받습니다:

| 필드              | 기본값                                                                                                                                           | 의미                                                                                                                                                                                                                                                   |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`       | `true`, 단 네 개의 [선택적 멤버](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#enable-optional-member-tools)는 `false` | 멤버가 Claude에게 제공되는지 여부.                                                                                                                                                                                                                               |
| `defer_loading` | `false`                                                                                                                                       | 도구 검색을 위해 도구 세트의 정의가 지연되는지 여부. 활성화된 모든 멤버에서 같은 값으로 해석되어야 합니다. 네 개의 선택적 멤버를 비활성화된 상태로 두면, 도구 세트를 지연시키는 것은 나머지 27개에 설정하는 것을 의미합니다. [클라이언트 도구 세트](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/tool-reference#client-toolsets)를 참조하세요. |

### 멤버 도구 활성화 또는 비활성화

`configs`에는 변경하려는 멤버만 나열하세요. 생략한 모든 멤버는 기본값을 유지합니다. 예를 들어, 콘솔 읽기는 구현하지만 저수준 포인터나 키 유지 제어는 구현하지 않는 실행기는 `read_console`을 켜고 세 개의 멤버를 보류합니다:

```json
{
  "type": "browser_toolset_20260801",
  "configs": {
    "read_console": { "enabled": true },
    "left_mouse_down": { "enabled": false },
    "left_mouse_up": { "enabled": false },
    "hold_key": { "enabled": false }
  }
}
```

비활성화된 멤버는 Claude가 보는 정의에서 사라집니다. 그렇다고 Claude가 절대 그것을 지정하지 않는다는 보장은 없으므로, 여러분의 실행기는 여전히 그런 호출에 [오류 결과](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#return-errors-from-your-executor)로 응답합니다.

### 다른 도구와 결합

브라우저 사용 도구를 같은 `tools` 배열에서 여러분의 자체 도구 및 다른 Anthropic 제공 도구와 함께 선언하세요. 커스텀 도구는 멤버의 이름을 공유할 수 있습니다(예를 들어 여러분 자체의 `navigate`). `toolset_name`이 Claude의 호출을 구별하기 때문입니다. 하지만 다른 어떤 항목도 `browser`라는 이름을 가질 수 없으며, 요청은 브라우저 도구 세트 항목을 하나만 담을 수 있습니다.

[컴퓨터 사용 도구](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/computer-use-tool)와 함께 선언할 수도 있으며, 도구 세트든 이전 컴퓨터 사용 도구 버전이든 가능합니다. 둘은 각자의 좌표 프레임(여기서는 뷰포트 픽셀, 저기서는 데스크톱 스크린샷 픽셀)에서 독립적으로 작동하며, `screenshot`이나 `key`처럼 이름을 공유하는 멤버에 대한 Claude의 호출은 `toolset_name`으로 구별됩니다.

## 선택적 멤버 활성화

네 개의 멤버 도구는 기본적으로 비활성화되어 있습니다. `javascript_exec`와 `file_upload`는 조종된 페이지가 Claude에게 시킬 수 있는 일의 범위를 넓히기 때문이고, `read_console`과 `read_network`는 모든 브라우저 자동화 스택이 해당 로그를 제공할 수 있는 것은 아니며 페이지가 제어하는 콘텐츠가 Claude에게 도달하는 범위를 넓히기 때문입니다. 여러분의 실행기가 구현하고 작업에 필요할 때만 `configs`로 각각을 활성화하세요(예: `"configs": {"file_upload": {"enabled": true}}`).

### 파일 업로드

`file_upload`는 `<input type="file">` 요소의 파일을 직접 설정하며, 이는 네이티브 파일 선택기를 구동하는 것보다 더 안정적입니다. 호출에 요소의 신원이 필요하므로 `target`은 참조만 가능하며, `paths`, `document_ids`, 또는 둘 다를 받습니다:

* `paths`는 실행기 파일 시스템의 파일 경로로, 실행기가 여러분의 애플리케이션의 파일을 직접 읽을 수 있는 배포용입니다(다운로드의 `path`를 채우는 것과 같은 조건).
* `document_ids`는 여러분의 애플리케이션이 브라우저를 위해 준비한 파일의 식별자로, 그럴 수 없는 배포용입니다. 식별자의 의미는 여러분의 애플리케이션이 정의합니다. `paths`의 범위를 한정하는 것과 같은 방식으로, 이 작업을 위해 준비된 파일로 해석 범위를 한정하세요.

```json
{
  "type": "tool_use",
  "id": "toolu_01N7gVzFEfZjLjgsYwnrPgrF",
  "name": "file_upload",
  "toolset_name": "browser",
  "input": {
    "target": { "type": "ref", "ref": "ref_12" },
    "paths": ["/home/user/uploads/summary.pdf"],
    "tab_id": "tab-2"
  }
}
```

Claude는 신뢰할 수 없는 페이지를 읽는 동안 이 경로를 작성하므로, 제한 없는 구현은 악의적인 페이지가 실행기가 읽을 수 있는 모든 파일을 페이지가 제어하는 사이트로 업로드하도록 지시할 수 있게 합니다. 여러분의 실행기가 각 경로를 해석하고(심볼릭 링크와 `..` 세그먼트를 따라가며) 작업용 파일만 담고 있는 전용 허용 목록 업로드 디렉터리 밖의 것은 아무것도 받지 않을 때만 이 멤버를 활성화하세요. 이를 위해 브라우저의 다운로드 디렉터리를 재사용하지 마세요. 그렇게 하면 페이지가 브라우저로 하여금 다운로드하게 만든 모든 파일이 업로드 가능해집니다.

### 페이지에서 JavaScript 실행

`javascript_exec`는 Claude가 작성한 표현식을 페이지의 컨텍스트에서 실행하고 마지막 표현식의 값을 텍스트로 반환합니다. Claude는 `return` 문이 아니라 표현식을 작성합니다. 코드는 쿠키, 스토리지, 동일 출처 요청을 포함한 페이지의 전체 권한으로 실행됩니다. 자격 증명을 보유하지 않는 세션에서만 이 멤버를 활성화하고, [보안 고려 사항](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#security-considerations)의 도메인 허용 목록을 계속 적용하고, 반환된 값을 신뢰할 수 없는 입력으로 취급하고, Claude가 내보내는 코드를 로깅하세요.

### 콘솔 및 네트워크 활동 읽기

`read_console`은 탭의 콘솔 항목을 반환하고 `read_network`는 네트워크 요청을 반환하며, 각각 해당 탭의 이전 읽기 이후 누적된 항목당 한 줄의 텍스트입니다. 콘솔 줄은 로그, 경고, 또는 오류 항목을 담고, 네트워크 줄은 메서드, URL, 상태, MIME 타입, 타이밍을 담습니다. 항목은 여러분의 브라우저 자동화가 탭에 연결된 순간부터만 존재하므로, 빈 결과가 이미 열려 있던 탭에 트래픽이 없었다는 것을 의미하지는 않습니다.

이 멤버들은 Claude가 반복적인 스크린샷 없이 오작동하는 페이지(스피너 뒤의 실패한 요청, 작동하지 않는 버튼 뒤의 스크립트 오류)를 진단할 수 있게 합니다. 콘솔 및 네트워크 항목은 페이지가 제어하며 요청 URL의 토큰 같은 비밀을 담고 있는 경우가 많으므로, Claude의 컨텍스트에 넣고 싶지 않은 자격 증명 같은 값은 가리고 매우 긴 항목은 반환하기 전에 잘라내세요.

## `browser_state`로 탭 추적하기

Claude는 `tab_id`로 탭을 지정하며, 어떤 탭이 존재하는지에 대한 기준 정보(source of truth)는 여러분의 애플리케이션이 가지고 있습니다. 이 상태는 `browser_state` 콘텐츠 블록으로 보고하는데, Claude는 이 블록을 직접 보지 않습니다. API가 이 블록으로부터 Claude가 읽는 텍스트를 렌더링합니다.

```json
{
  "type": "browser_state",
  "tabs": [
    {
      "tab_id": "tab-1",
      "title": "Documentation",
      "url": "https://example.com/docs",
      "active": true
    },
    { "tab_id": "tab-2", "title": "Pricing", "url": "https://example.com/pricing" }
  ]
}
```

* `tabs`는 호출 이후 열려 있는 탭의 전체 목록이며, 변경분(delta)이 아닙니다. 비어 있을 수 있으며, 비어 있지 않을 때는 정확히 하나의 항목에 `"active": true`가 있어야 합니다.
* `state_changes`(여기에는 표시되지 않음)는 호출의 부수 효과를 보고합니다. 호출이 연 탭 중 호출이 끝날 때까지 열려 있는 각 탭에 대한 `tab_opened` 항목(해당 `tab_id`는 `tabs`에도 있어야 함)과 [다운로드 이벤트](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#report-downloads)가 여기에 포함됩니다. 보고할 내용이 없으면 이 필드를 생략하세요. 빈 배열은 거부됩니다.
* 이 블록은 브라우저 멤버 호출에 응답하는 결과에만, `tool_result`당 최대 한 번 보내고, `is_error: true`인 결과에는 절대 보내지 마세요. "보고할 탭 상태 없음"은 블록을 생략하는 것으로 표현합니다.
* API는 `tabs`와 `state_changes`의 다운로드 항목을 Claude를 위한 텍스트로 렌더링합니다. 다음 두 섹션과 [다운로드 보고하기](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#report-downloads)에서 그 텍스트를 보여 줍니다.

**`tab_id` 값은 여러분이 할당합니다.** 자동화 라이브러리의 페이지 식별자나 자체 카운터 등 안정적인 문자열이면 무엇이든 사용할 수 있습니다. 단, 이전 결과에서 해당 식별자를 가진 탭이 아직 열려 있는 것으로 나열되어 있는 동안에는 그 `tab_id`를 재사용하지 않아야 합니다. API는 이 블록에 대해 다음 제한을 적용합니다.

* 각 `tab_id`, `title`, `url`은 최대 4,096자까지 가능하며, `tab_id`는 비어 있지 않아야 하고, 어느 것도 제어 문자(줄바꿈 포함)나 Unicode 줄 구분자 또는 단락 구분자를 포함할 수 없습니다.
* 하나의 블록은 최대 100개의 탭과 200개의 상태 변경을 나열할 수 있습니다.
* Claude가 `switch_tab`과 `close_tab`에 전달하는 `tab_id`에도 동일한 제한이 적용됩니다. API가 이를 결과 텍스트로 렌더링하기 때문입니다. 따라서 `tab_id`가 이 제한을 위반하는 호출에는 `browser_state` 블록 대신 오류 결과로 응답하세요.

<Warning>
  탭 제목과 URL은 페이지에서 가져오며 Claude가 읽는 텍스트로 렌더링되므로, "prompt injection"(프롬프트 인젝션)의 공격 표면이 됩니다. API는 탭 URL을 그대로 렌더링하므로, `tabs`를 채우기 전에 페이지가 제공한 URL을 정제하세요. API는 제목을 렌더링할 때 큰따옴표와 백슬래시를 이스케이프하므로 제목을 미리 이스케이프하지 마세요(미리 이스케이프한 제목은 Claude에게 이중으로 이스케이프된 상태로 전달됩니다). 그래도 의심스러운 제목을 잘라내거나 제외하는 것은 여전히 가치가 있습니다. 다운로드 항목의 `url`, `path`, `error`도 Claude가 읽는 텍스트로 렌더링되므로 마찬가지로 신뢰할 수 없는 값으로 취급하세요. API는 제목과 마찬가지로 이 값들을 따옴표로 감싸고 이스케이프합니다. API가 적용하는 길이 및 문자 제한은 최소한의 기준일 뿐, 방어 수단이 아닙니다.
</Warning>

### 탭 관리 결과

`new_tab`, `switch_tab`, `close_tab`, `list_tabs`의 경우, 성공 결과의 `content`는 텍스트나 이미지 없이 정확히 하나의 `browser_state` 블록이며, Claude가 보는 텍스트는 API가 작성합니다. `new_tab` 결과의 블록은 또한 `active: true`로 표시된 항목과 `tab_id`가 일치하는 `tab_opened` 상태 변경을 정확히 하나 포함해야 합니다.

| 멤버           | Claude가 보는 텍스트                                                                                                |
| ------------ | ------------------------------------------------------------------------------------------------------------- |
| `switch_tab` | `Switched to tab {tab_id}`, 호출의 `input.tab_id`에서 가져옴                                                          |
| `close_tab`  | `Closed tab {tab_id}`, 호출의 `input.tab_id`에서 가져옴                                                               |
| `new_tab`    | `Created new tab with tab_id: {tab_id}, URL: {url}. It is now the current tab.`, `active: true`로 표시된 항목에서 가져옴 |
| `list_tabs`  | `Available tabs:` 다음에 탭당 한 줄씩, 또는 `tabs`가 비어 있으면 `No tabs available`                                          |

블록에 두 개의 탭이 나열되고 첫 번째 탭이 활성 상태인 `list_tabs` 결과는 다음과 같이 렌더링됩니다. 각 줄은 두 칸 들여쓰기되며 활성 탭에만 `(current)`가 붙습니다.

```text wrap
Available tabs:
  • tab_id tab-1: "Documentation" (https://example.com/docs) (current)
  • tab_id tab-2: "Pricing" (https://example.com/pricing)
```

이러한 멤버 중 하나에 대한 오류 결과는 그 반대입니다. `content`에 일반 오류 텍스트, `is_error: true`, 그리고 `browser_state` 블록 없음입니다.

예를 들어, Claude가 `new_tab`을 호출하면(`input`은 비어 있음), 여러분의 실행기(executor)는 탭을 열고 활성화한 다음 하나의 `tab_opened` 항목과 함께 목록을 반환합니다.

```json
{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_01WvHSbQVV9j5nWGvTmk4vNL",
      "toolset_name": "browser",
      "content": [
        {
          "type": "browser_state",
          "tabs": [
            { "tab_id": "tab-1", "title": "Documentation", "url": "https://example.com/docs" },
            { "tab_id": "tab-2", "title": "Pricing", "url": "https://example.com/pricing" },
            { "tab_id": "tab-3", "title": "", "url": "about:blank", "active": true }
          ],
          "state_changes": [{ "type": "tab_opened", "tab_id": "tab-3" }]
        }
      ]
    }
  ]
}
```

Claude는 `Created new tab with tab_id: tab-3, URL: about:blank. It is now the current tab.`을 보게 됩니다. 여기서처럼 탭이 열린 시점의 URL을 보고하고, 나중에 리디렉션된 URL을 보고하지 마세요. 이후 결과에서는 탭의 그 시점 현재 URL을 보고합니다.

### 다른 결과의 탭 컨텍스트

다른 모든 멤버에서 이 블록은 선택 사항입니다. 열린 탭 집합, 활성 탭, 또는 탭의 제목이나 URL이 변경되었을 때, 또는 보고할 `state_changes`가 있을 때 보내고, 항상 전체 `tabs` 목록을 포함하세요. 결과에 텍스트와 `browser_state` 블록이 모두 있으면, API는 해당 결과의 텍스트에 `Tab Context` 푸터를 빈 줄로 구분하여 덧붙이므로, Claude는 별도의 `list_tabs` 호출 없이 새 상태를 받습니다.

```text wrap
Tab Context:
- Executed on tab_id: tab-1
- Available tabs:
  • tab_id tab-1: "Documentation" (https://example.com/docs)
  • tab_id tab-2: "Pricing" (https://example.com/pricing)
```

`Executed on`은 호출이 실행된 탭을 지정하는데, `tab_id` 입력이 있으면 그 값이고 없으면 활성 탭입니다. 푸터의 탭 줄에는 `(current)` 표시가 없습니다. 이 텍스트를 직접 덧붙이지 마세요. 구조화된 블록을 보내고 API가 렌더링하도록 하세요. 푸터는 중복 제거되므로, 동일한 탭 상태는 이후 결과에서 다시 렌더링되지 않으며 블록을 넉넉하게 채워도 비용이 들지 않습니다.

블록이 있어도 푸터가 렌더링되지 않는 세 가지 경우가 있습니다.

* 모든 `zoom` 결과.
* `text` 블록이 없는 결과(예: 이미지만 있는 `screenshot` 결과). 해당 결과에 대해서는 아무것도 렌더링되거나 기억되지 않으며, 탭 컨텍스트는 텍스트와 `browser_state` 블록을 모두 포함하는 다음 결과에 나타납니다. 따라서 같은 결과에서 Claude가 탭 변경을 보게 하려면 이미지와 함께 짧은 텍스트 블록을 포함하세요. 예외는 블록이 [다운로드 이벤트](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#report-downloads)를 보고하는 결과입니다. API는 다운로드 줄을 텍스트 블록으로 추가하며, 텍스트가 있는 다른 결과와 마찬가지로 그 뒤에 푸터가 이어집니다.
* `tab_id`가 없는 호출에서 `tabs` 목록이 비어 있는 결과. 지정할 탭이 없기 때문입니다.

예를 들어, 이 세션 앞부분에서 Claude가 "Pricing" 링크(`ref_5`)를 클릭했을 때, 페이지는 Claude가 요청하지 않은 새 탭에서 이를 열었고, 보고가 없다면 Claude는 이를 발견하기 위해 `list_tabs`를 호출해야 했을 것입니다. 클릭 확인 응답과 함께, `state_changes`에 열린 탭을 지정하고 실행기가 활성 상태로 남겨둔 탭을 표시한 블록을 반환하세요.

```json
{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_01EgTXj1FjE2FCTt2zNFWLao",
      "toolset_name": "browser",
      "content": [
        { "type": "text", "text": "Clicked element ref_5." },
        {
          "type": "browser_state",
          "tabs": [
            {
              "tab_id": "tab-1",
              "title": "Documentation",
              "url": "https://example.com/docs",
              "active": true
            },
            { "tab_id": "tab-2", "title": "Pricing", "url": "https://example.com/pricing" }
          ],
          "state_changes": [{ "type": "tab_opened", "tab_id": "tab-2" }]
        }
      ]
    }
  ]
}
```

Claude는 `Clicked element ref_5.` 다음에 앞서 보여준 Tab Context 푸터를 보게 됩니다. 실패한 호출 중에 열린 탭은 `tab_opened` 항목을 받지 않습니다. 오류 결과에는 `browser_state`가 없기 때문입니다. 대신 다음 성공 결과의 `tabs` 목록에 나타납니다. 배치에서는 변경이 발생한 호출의 결과에 블록을 첨부하고, 같은 턴의 이전 결과가 동일한 상태를 보고했더라도 모든 성공적인 탭 관리 결과에 자체 블록을 제공하세요.

### 다운로드 보고

클릭이나 탐색이 파일 다운로드를 시작하면, 다운로드가 발생한 호출의 결과에서 `state_changes`로 보고하고, 여러분이 할당한 `download_id`로 여러 결과에 걸쳐 연관시키세요. 다운로드는 비동기적으로 실행되며 여러 결과에 걸칠 수 있으므로, 세 가지 이벤트 유형이 있습니다.

| `type`               | 필드                                           | 보내는 시점                                                                                                                                                                                                                              |
| -------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `download_started`   | `download_id`, `url`                         | 다운로드가 시작된 호출의 결과에서. `url`은 리디렉션 이후 파일이 제공되는 최종 URL입니다.                                                                                                                                                                              |
| `download_completed` | `download_id`, `url`, `path?`, `size_bytes?` | 다운로드가 완료될 때 실행 중인 이후 호출의 결과에서. 같은 환경의 다른 도구(예: [bash 도구](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/bash-tool) 또는 `file_upload`)가 해당 위치에서 파일을 읽을 수 있을 때만 `path`를 포함하세요. 그렇지 않으면 `download_id`가 다운로드의 유일한 식별자입니다. |
| `download_failed`    | `download_id`, `url`, `error?`               | 다운로드가 실패하거나 취소되었을 때. 브라우저가 이유를 제공하면 `error`에 담습니다.                                                                                                                                                                                  |

API는 각 항목을 Claude를 위한 한 줄의 텍스트로, 항목이 나타나는 순서대로 렌더링합니다. 이 줄들은 결과의 텍스트 뒤에 빈 줄로 구분되어, Tab Context 푸터보다 앞에 추가됩니다. `zoom` 및 탭 관리 결과를 포함한 모든 종류의 멤버 결과에 이 줄들이 포함됩니다. `text` 블록이 없는 결과에는 별도의 텍스트 블록으로 추가됩니다. 각 줄에는 `download_id`와 `url`이 표시되며, 값을 보낸 경우 `path`와 `size_bytes`(`download_completed`의 경우) 또는 `error`(`download_failed`의 경우)도 표시됩니다. 자체 텍스트에서 다운로드를 설명할 필요는 없습니다. API는 `url`, `path`, `error`를 큰따옴표로 감싸고 그 안의 큰따옴표와 백슬래시를 이스케이프하므로, 이 값들을 미리 이스케이프하지 마세요.

예를 들어 Pricing 탭에서 "Download price list (CSV)"(`ref_8`)를 클릭하면 다운로드가 시작되므로, 클릭 결과에는 `download_id`가 `"dl-1"`이고 파일 URL을 담은 `download_started` 항목이 포함됩니다. 다운로드는 이후 `screenshot` 호출이 실행되는 동안 완료되므로, 해당 결과의 `content`에는 이미지, `Screenshot captured.` 같은 텍스트 블록, 그리고 같은 `download_id`로 완료를 보고하는 다음 `browser_state` 블록이 포함됩니다.

```json
{
  "type": "browser_state",
  "tabs": [
    { "tab_id": "tab-1", "title": "Documentation", "url": "https://example.com/docs" },
    {
      "tab_id": "tab-2",
      "title": "Pricing",
      "url": "https://example.com/pricing",
      "active": true
    }
  ],
  "state_changes": [
    {
      "type": "download_completed",
      "download_id": "dl-1",
      "url": "https://example.com/pricing/price-list.csv",
      "path": "/home/user/downloads/price-list.csv",
      "size_bytes": 48213
    }
  ]
}
```

Claude는 `Screenshot captured.` 뒤에 빈 줄과 다음과 같은 줄을 보게 됩니다.

```text wrap
Download completed with download_id: dl-1, URL: "https://example.com/pricing/price-list.csv". Saved to "/home/user/downloads/price-list.csv". Size: 48213 bytes.
```

다운로드 보고는 다음 규칙을 따릅니다.

* 하나의 블록에서 `download_id`당 최대 하나의 항목만 허용되므로, 같은 호출 중에 시작되고 완료된 다운로드는 `download_completed`만 보고합니다.
* `is_error: true` 결과에는 절대 `state_changes`를 보내지 마세요. 실패한 호출 중에 발생한 다운로드 이벤트는 다음 성공 결과에서 보고하세요.
* `state_changes`는 진행 중인 다운로드의 목록이 아닙니다. 각 이벤트는 한 번만 보고하세요.
* 각 항목은 해당 `type`이 선언한 필드만 포함합니다. `size_bytes`는 음이 아닌 정수이고, `download_id`는 비어 있지 않으며, `download_id`, `url`, `path`, `error`는 각각 최대 4,096자이고 제어 문자나 Unicode 줄 구분자 또는 단락 구분자를 포함하지 않습니다. `url`은 원격 서버에서 오며 리디렉션 이후 서명된 쿼리 문자열 자격 증명을 포함하는 경우가 많으므로, Claude의 컨텍스트에 넣고 싶지 않은 쿼리 매개변수를 제거하고, 보고하거나 파일 시스템 경로에 사용하기 전에 정제하세요.

## 오류 처리

실패한 호출은 일반 오류 결과로 Claude에게 보고하세요. `is_error: true`, 무엇이 잘못되었는지 설명하는 텍스트 콘텐츠, 그대로 반영한 `toolset_name`, 그리고 `browser_state` 블록 없음입니다.

### 실행기에서 오류 반환하기

Claude는 오류 텍스트를 읽고 적응하므로 오류 텍스트를 구체적으로 작성하세요. `Error: Navigation to https://example.com/status timed out after 30 seconds. The page may be unavailable.`은 Claude가 조치할 수 있는 정보를 주지만, 단순한 `Error: navigation failed`는 그렇지 않습니다. 다른 일반적인 경우는 다음과 같습니다.

<AccordionGroup>
  <Accordion title="거부된 탐색 스킴">
    ```json
    {
      "type": "tool_result",
      "tool_use_id": "toolu_01LeUTyqkhRxBFq1QTG3pkwN",
      "toolset_name": "browser",
      "is_error": true,
      "content": "Error: Navigation refused. Only http and https URLs are allowed."
    }
    ```
  </Accordion>

  <Accordion title="오래되었거나 알 수 없는 요소 참조">
    ```json
    {
      "type": "tool_result",
      "tool_use_id": "toolu_01D7FLrfh4GYq7yT1ULFeyMV",
      "toolset_name": "browser",
      "is_error": true,
      "content": "Error: ref_3 is stale or not found on the current page. Re-read the page to get fresh references."
    }
    ```
  </Accordion>

  <Accordion title="비활성화되었거나 구현되지 않은 멤버">
    ```json
    {
      "type": "tool_result",
      "tool_use_id": "toolu_013h2Q55HcNwVyapSpy2s5ZG",
      "toolset_name": "browser",
      "is_error": true,
      "content": "Error: javascript_exec is not enabled in this environment."
    }
    ```
  </Accordion>

  <Accordion title="턴 내 이전 실패 이후 건너뜀">
    [배치 작업](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#batch-actions)의 `ref_3`에 대한 `left_click`이 앞서 보여준 오래된 참조 오류로 실패하면, 그 뒤의 `type` 및 `key` 호출은 각각 다음 결과를 받습니다.

    ```json
    {
      "type": "tool_result",
      "tool_use_id": "toolu_01FkP8rTz6uYh2mNq4LsXw7v",
      "toolset_name": "browser",
      "is_error": true,
      "content": "Not executed: an earlier action in this turn failed."
    }
    ```
  </Accordion>
</AccordionGroup>

### 요청 오류

API는 툴셋 항목과 대화 내 모든 멤버 `tool_use` 및 `tool_result` 블록을 검증합니다. 하나라도 형식이 잘못되면, API는 Claude가 실행되기 전에 `invalid_request_error`를 반환합니다. 다음 표에서 왼쪽 열은 여러분이 보낸 것을 나타냅니다.

| 요청                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | 실패 이유와 조치 방법                                                                                                                                                                                               |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 툴셋 항목이 허용하지 않는 옵션 또는 조합. 예: 항목 자체의 `name`, `strict: true`, `input_examples`, `defer_loading`, 멤버 이름이 아닌 `configs` 키, 멤버의 `configs` 값에서 `enabled` 또는 `defer_loading` 이외의 필드([툴셋 구성](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#configure-the-toolset)), `defer_loading` 값이 서로 다른 활성화된 멤버들([툴셋 구성](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#configure-the-toolset)), 활성화된 멤버를 하나도 남기지 않는 `configs`, `allowed_callers`의 코드 실행 호출자, 요청의 레거시 `fine-grained-tool-streaming-2025-05-14` 베타 헤더, `browser` 또는 멤버를 지정하는 `tool` 유형의 `tool_choice`, 또는 두 번째 브라우저 툴셋 항목이나 `browser`라는 이름의 다른 도구 | 이들은 클라이언트 툴셋에서 지원되지 않습니다. 각 규칙과 대안은 [클라이언트 툴셋](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/tool-reference#client-toolsets)을 참조하세요.                                                       |
| `"toolset_name": "browser"` 없이 또는 다른 값으로 멤버 호출에 응답하는 `tool_result`, 또는 멤버 호출이 아닌 호출의 결과에 있는 `toolset_name`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | 멤버 결과에는 `toolset_name`을 정확히 반영하고, 멤버 결과에만 반영하세요.                                                                                                                                                           |
| 일치하는 `tool_result`가 없는 이전 턴의 멤버 `tool_use`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | 실패 후 실행하지 않은 것을 포함하여 모든 멤버 호출에 응답하세요.                                                                                                                                                                      |
| 멤버 결과에 있는 `text`, `image`, `browser_state` 이외의 콘텐츠 블록                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | 멤버 결과는 이 세 가지 블록 유형만 허용합니다.                                                                                                                                                                                |
| [`browser_state`로 탭 추적하기](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#track-tabs-and-page-state)의 규칙을 위반하는 `browser_state` 블록. 예: `is_error: true` 결과나 브라우저 멤버 호출에 응답하지 않는 결과에 있는 블록, 하나의 결과에 둘 이상의 블록, 정확히 하나의 `active: true` 항목이 없는 비어 있지 않은 `tabs`, 중복된 `tab_id`, 빈 `state_changes` 배열, `tab_id`가 `tabs`에 없는 `tab_opened`, 하나의 `download_id`에 대한 두 개의 상태 변경 또는 해당 `type`이 선언하지 않은 상태 변경 필드([다운로드 보고](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#report-downloads)), 또는 제한을 초과한 필드                                                                                                  | 블록을 수정하세요. "보고할 것 없음"은 블록이나 `state_changes` 필드를 생략하는 것으로 표현하며, 절대 빈 값으로 표현하지 않습니다.                                                                                                                         |
| `content`가 정확히 하나의 `browser_state` 블록이 아닌 성공적인 `new_tab`, `switch_tab`, `close_tab`, `list_tabs` 결과, 또는 활성 탭과 일치하는 `tab_opened`가 정확히 하나가 아닌 `new_tab` 결과                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | API는 이 결과들을 블록으로부터 렌더링하며 정확히 그 형태의 블록이 필요합니다. [탭 관리 결과](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#tab-management-results)를 참조하세요.                                     |
| 모델의 [이미지 크기 제한](https://platform.claude.com/docs/ko/build-with-claude/vision#evaluate-image-size)을 초과하거나, 이전 결과의 스크린샷과 `zoom` 이미지를 포함하여 요청에 [20개 이상의 이미지](https://platform.claude.com/docs/ko/build-with-claude/vision#request-limits)가 있을 때 적용되는 더 엄격한 이미지당 제한을 초과하는 결과 내 `image`                                                                                                                                                                                                                                                                                                                                                                           | API는 툴셋 이미지를 축소하지 않습니다. 반환하기 전에 스크린샷 크기를 조정하세요([이미지 제한에 맞게 스크린샷 크기 조정](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/computer-use-tool#handle-coordinate-scaling-for-higher-resolutions)). |
| `browser_toolset_20260801`을 지원하지 않는 `model`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | 지원되는 모델은 [호환성](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-tool#compatibility)을 참조하세요.                                                                                       |

## 제한 사항

* **플랫폼 가용성:** 브라우저 사용은 Claude API와 [Google Cloud](https://platform.claude.com/docs/ko/build-with-claude/claude-on-vertex-ai)에서 사용할 수 있습니다.
* **전체 입력 스트리밍만 지원:** 스트리밍할 때 각 멤버의 `input`은 하나의 완전한 `input_json_delta`로 도착합니다([클라이언트 툴셋](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/tool-reference#client-toolsets)).
* **요소 참조는 최선 노력(best-effort) 방식:** 매우 동적인 페이지(가상화된 목록, 캔버스로 렌더링된 인터페이스, 스크롤 시 다시 렌더링되는 페이지)는 안정적인 참조를 노출하지 않을 수 있으며, 이 경우 Claude는 스크린샷과 좌표 클릭으로 대체합니다.
* **`read_console`과 `read_network`는 브라우저 자동화에 의존:** 브라우저 자동화가 캡처할 수 있는 것만, 그리고 탭에 연결된 시점부터만 보고합니다.
* **일반적인 에이전트 제한 사항 적용:** 지연 시간(latency), 비전 정확도, 프롬프트 인젝션 위험은 컴퓨터 사용에서 그대로 이어지며(컴퓨터 사용 도구의 [제한 사항](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/computer-use-tool#understand-computer-use-limitations) 참조), [프롬프팅으로 모델 성능 최적화](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/computer-use-tool#optimize-model-performance-with-prompting), [스크린샷 기록 관리](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/computer-use-tool#manage-screenshot-history), [구현 모범 사례 따르기](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/computer-use-tool#follow-implementation-best-practices)(작업 지연, 작업 검증, 로깅)의 지침은 브라우저 실행기에도 적용됩니다.

## 가격 및 데이터 보존

브라우저 사용은 표준 [도구 사용 가격](https://platform.claude.com/docs/ko/agents-and-tools/tool-use/overview#pricing)을 따릅니다. 브라우저 사용 도구를 사용할 때:

**도구 세트 정의 오버헤드:** 기본 멤버와 함께 `browser_toolset_20260801`을 선언하면 요청에 약 6,600개의 입력 토큰이 추가되며(Claude Sonnet 5에서는 약 6,670개, 기타 지원 모델에서는 약 6,610개), 여기에는 멤버 도구 정의와 도구 사용 시스템 프롬프트가 포함됩니다. 네 가지 선택적 멤버를 모두 활성화하면 약 880개의 토큰이 추가되며, `configs`로 멤버를 비활성화하면 토큰 수가 줄어듭니다. 요청의 정확한 토큰 수는 응답의 `usage`에 보고되며, [토큰 카운팅 엔드포인트](https://platform.claude.com/docs/ko/build-with-claude/token-counting)를 사용하여 미리 추정할 수 있습니다.

**추가 토큰 소비:**

* 도구 결과로 반환되는 스크린샷 및 확대 이미지는 이미지 입력으로 청구됩니다([비전 가격](https://platform.claude.com/docs/ko/build-with-claude/vision#evaluate-image-size) 참조)
* 접근성 트리, 페이지 텍스트, 콘솔 또는 네트워크 항목 등 Claude에 반환되는 텍스트 도구 결과

<Note>
  브라우저 사용과 함께 컴퓨터 사용 도구, bash 도구, 텍스트 편집기 도구 또는 자체 도구를 함께 사용하는 경우, 해당 도구들은 각각의 페이지에 문서화된 대로 자체적인 토큰 비용이 있습니다.
</Note>

브라우저 세션, 다운로드, 업로드된 파일은 여러분의 환경에 남습니다. 여러분이 반환하는 스크린샷, 페이지 텍스트, 탭 상태는 API 요청 콘텐츠의 일부이며 표준 보존 정책을 따르거나, ZDR 계약이 있는 경우 해당 계약을 따릅니다. 브라우저 사용 도구는 ZDR 적격입니다. 기능별 보존 기간과 적격 여부는 [API 및 데이터 보존](https://platform.claude.com/docs/ko/manage-claude/api-and-data-retention)을 참조하세요.

## 다음 단계

<CardGroup cols={2}>
  <Card title="SDK 도구 세트를 사용한 브라우저 및 컴퓨터 사용" icon="code" href="https://platform.claude.com/docs/ko/agents-and-tools/tool-use/browser-use-sdk">
    파트너의 드라이버로 시작하거나 Python 또는 TypeScript로 직접 작성하세요. SDK가 루프와 구성한 검사를 실행합니다.
  </Card>

  <Card title="컴퓨터 사용 도구" icon="computer" href="https://platform.claude.com/docs/ko/agents-and-tools/tool-use/computer-use-tool">
    작업이 브라우저를 벗어날 때 Claude에게 전체 데스크톱 제어 권한을 부여하세요. 해당 구현 지침은 브라우저 실행기에도 적용됩니다.
  </Card>

  <Card title="도구 호출 처리하기" icon="wrench" href="https://platform.claude.com/docs/ko/agents-and-tools/tool-use/handle-tool-calls">
    `tool_result` 블록의 형식을 지정하고, 이미지와 오류를 반환하고, 대화를 계속하세요.
  </Card>

  <Card title="도구 레퍼런스" icon="book" href="https://platform.claude.com/docs/ko/agents-and-tools/tool-use/tool-reference">
    클라이언트 도구 세트와 Anthropic이 제공하는 기타 모든 도구를 버전 및 매개변수와 함께 살펴보세요.
  </Card>
</CardGroup>
