콘텐츠로 이동

브라우저 사용 도구 (Browser Use Tool)

브라우저 사용 도구를 쓰면 Claude가 여러분의 애플리케이션이 실행하는 브라우저에서 웹페이지를 탐색하고, 읽고, 상호작용할 수 있어요. 페이지와는 구조(접근성 트리, 요소, 폼, 탭)를 통해서도, 픽셀(스크린샷과 뷰포트 좌표)을 통해서도 함께 작업하는데요, 컴퓨터 사용 도구는 스크린샷과 좌표만으로 전체 데스크톱을 다루는 것과 대비돼요. 이 도구는 Anthropic이 정의한 클라이언트 툴셋이라서, tools 배열에 browser_toolset_20260801 항목 하나만 넣으면 기본적으로 27개의 멤버 도구(navigate, read_page, left_click, screenshot 등)가 제공되고, 활성화하면 추가로 4개(javascript_exec, file_upload, read_console, read_network)가 더 붙어요. 모든 호출은 여러분의 애플리케이션이 자기 브라우저 자동화로 실행하며, Anthropic 쪽에서 실행되는 건 없어요. 현재는 Claude Managed Agents에서는 사용할 수 없어요. 이 문서에서 "여러분의 애플리케이션"은 Messages API를 호출하는 에이전트 루프를, "여러분의 실행기(executor)"는 그중에서 브라우저를 구동하고 도구 결과를 만들어내는 부분을 가리켜요.

컴퓨터 사용 도구보다 브라우저 사용 도구를 골라야 하는 경우는 작업이 웹페이지 안에 머무를 때예요. Claude가 페이지의 구조를 읽고, 좌표뿐 아니라 참조(reference)로도 요소를 조작하고, 폼 값을 직접 설정하고, 여러 탭을 넘나들 수 있는데다 데스크톱을 실행할 필요도 없거든요. 그런데 Claude가 그냥 지정된 페이지를 읽기만 하면 되거나 웹에서 자료를 찾으면 될 때는 웹 페치 도구나 웹 검색 도구가 더 가벼워요. 둘 다 서버 도구라서 API가 브라우저 없이 실행해 주거든요. 페이지가 JavaScript로 콘텐츠를 만들거나, 작업이 읽기만이 아니라 페이지에 작용하는 것이라면 브라우저 사용을 선택하세요.

브라우저 사용으로 Claude는 실제 웹페이지를 읽고 작용하므로, 페이지가 주는 모든 것은 신뢰할 수 없는 입력이고 Claude가 취하는 행동은 실제 영향을 줄 수 있어요. 배포 전에 보안 고려사항(Security considerations)을 꼭 확인하세요.

빠른 시작 (Quick start)

브라우저 사용 도구는 Claude API와 Google Cloud에서 사용할 수 있어요. Messages API 요청의 tools 배열에 browser_toolset_20260801 타입 항목 하나를 이름 없이 추가하면 됩니다.

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-opus-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)

Claude의 첫 응답은 stop_reason: "tool_use"로 끝나고, 멤버 도구를 가리키는 tool_use 블록을 하나 이상 담아요. 각 블록은 name에 멤버 도구 이름을, 그리고 "toolset_name": "browser"를 갖습니다:

{
  "id": "msg_01HCDu4XSTLzTAcodEQ58vDo",
  "type": "message",
  "role": "assistant",
  "model": "claude-opus-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
}

여러분의 실행기가 navigateread_page를 실행하고, 애플리케이션은 다음 요청에서 블록당 tool_result 하나씩을 toolset_name을 그대로 붙여 돌려줘요. navigate 결과는 탭에 로드된 상태를 browser_state 블록으로 보고하고, read_page 결과는 모든 요소에 참조가 붙어 있는 텍스트입니다:

{
  "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를 클릭해 getting-started 페이지를 열면 돼요. 링크를 스크린샷에서 직접 찾을 필요가 없어졌죠.

브라우저 사용이 어떻게 동작하나요 (How browser use works)

브라우저 사용은 에이전트 루프로 동작해요. Claude가 멤버 도구 호출을 돌려주면, 여러분의 실행기가 브라우저에서 실행하고, 결과를 돌려주고, Claude가 텍스트로 답할 때까지 반복합니다.

1. 브라우저 사용 도구와 사용자 프롬프트를 Claude에 제공 API 요청에 browser_toolset_20260801 항목을 추가하고, 필요하면 다른 도구도 추가하세요. 웹페이지 작업을 요청하는 사용자 프롬프트를 포함하세요. 예: "Open example.com/docs and tell me how to get started."

2. Claude가 멤버 도구 호출로 응답 Claude는 한 번의 어시스턴트 턴에 tool_use 블록을 하나 이상 돌려줘요. 한 턴에 여러 개가 오면 그게 배치 동작(batch action)입니다(예: left_clicktypekey). 각 블록의 name은 멤버 이름이고, 각각 "toolset_name": "browser"를 갖고, input에는 멤버의 파라미터만 담기며 action 필드는 없어요. 응답의 stop_reasontool_use입니다.

3. 호출을 순서대로 실행하고 결과를 돌려줌 response.content의 모든 tool_use 블록을 반복하세요(정확히 하나라고 가정하지 마세요). 나중 호출이 보통 앞선 호출에 의존하므로 나온 순서대로 순차 실행합니다. 새 사용자 메시지에서 블록마다 tool_result를 하나씩, tool_use_id로 짝지어 돌려주고 각각에 "toolset_name": "browser"를 그대로 붙여요. 모든 호출에 답해야 하며, 하나라도 빠지면 다음 요청이 거부됩니다. 호출이 실패하면 그 블록에 is_error: true와 텍스트 설명을 붙여 돌려주고, 배치 동작(Batch actions)의 정지 규칙을 턴의 모든 이후 블록에도 적용하세요.

4. 작업이 끝날 때까지 Claude가 계속 진행 Claude가 결과(페이지 텍스트, 접근성 트리, 스크린샷, 탭 상태)를 읽고 더 필요하면 멤버 호출을 다시 돌려주며, 그러면 3단계로 돌아가요. 아니면 사용자에게 텍스트 응답을 돌려줍니다.

이 루프의 도구 호출 단계 골격을 두 부분으로 보여드릴게요. 먼저 여러분의 브라우저 자동화를 대신하는 스텁(stub) 멤버 핸들러입니다. 다섯 멤버(navigate, read_page, left_click, type, screenshot)는 결과 내용이 되는 텍스트(또는 screenshot의 경우 이미지 블록)를 돌려주고, 디스패처는 구현하지 않은 멤버에 대해 오류를 던져요.

# Placeholder image data; a real executor captures the viewport and returns the PNG bytes
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):
    # A target is an element reference from read_page or find, or a viewport coordinate
    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 answers with an image block rather than text: return the result content list
    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()
    # Handle other actions as needed
    raise ValueError(f"Unknown or unimplemented member: {name}")

두 번째 부분은 배치를 순서대로 실행하고, 각 블록을 핸들러에 디스패치하며, 모든 결과에 toolset_name을 붙이고, 배치 동작에서 나온 정지 규칙을 적용해 핸들러 오류를 오류 결과로 바꿉니다. 이걸 호출하는 샘플링 루프는 에이전트 루프 이해하기(Understand the agent loop)에 나온 것과 동일하며, tools에 브라우저 툴셋이 들어 있어요.

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:
        # Only the browser toolset is declared; route other tools here if you add them
        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:
                # A string or a list of content blocks; a real executor also adds a
                # browser_state block to navigation and tab-management results
                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

각 블록은 name만이 아니라 (toolset_name, name) 쌍으로 디스패치하세요. 같은 요청의 사용자 정의 도구가 멤버와 같은 이름을 공유할 수 있기 때문이에요. 클라이언트 툴셋(Client toolsets) 문서가 두 툴셋이 공유하는 이 계약의 나머지를 설명해요. 실행기가 구현하지 않거나 비활성화한 멤버를 Claude가 부르면, 그 블록을 버리지 말고 오류 결과로 답하세요.

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

배치 동작 (Batch actions)

멤버 호출이 여러 개인 턴은 배치 동작이에요. 나온 순서대로 실행하고, 첫 실패에서 멈추고, 이후의 모든 호출에는 is_error: true와 정확한 텍스트 Not executed: an earlier action in this turn failed.로 답합니다. 배치는 병렬 도구 사용과 동일한 응답 형태를 쓰는 대신, 블록을 동시에가 아니라 순서대로 실행한다는 차이가 있어요. 여기서는 Claude가 앞서 찾은 검색창을 클릭하고, 질의를 입력하고, Enter를 누르는 걸 한 턴에 처리합니다:

{
  "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" }
    }
  ]
}

여러분의 애플리케이션은 하나의 사용자 메시지에 tool_result 세 개를 돌려주는데, 각각 toolset_name을 갖고 Clicked element ref_3. 같은 짧은 텍스트 확인을 담아요. Enter를 누르면 결과 페이지가 로드되므로 key 결과에는 탭의 갱신된 URL을 담은 browser_state 블록도 함께 들어가요(다른 결과의 탭 맥락 참고). 클릭이 실패했다면 그 결과에는 오류 텍스트가, 나머지 두 결과에는 정지 텍스트가 실려요(실행기의 오류 반환에서 설명).

모든 호출마다 스크린샷을 돌려줄 필요는 없어요. Claude는 보통 배치를 관찰 호출(screenshot, read_page, get_page_text)로 끝내고, 애플리케이션도 배치의 마지막 결과에 추가 content 블록으로 자신의 관찰(새 스크린샷이나 접근성 트리 등)을 붙여 왕복을 줄일 수 있어요. 탭 관리 결과는 정확히 browser_state 블록 하나여야 하므로, 탭 관리 호출이 아닌 마지막 결과에 붙이세요.

실행기가 왕복당 한 호출만 실행할 수 있다면 tool_choice에서 disable_parallel_tool_usetrue로 설정하세요. 그러면 Claude가 턴당 멤버 호출을 최대 하나만 돌려주는 대신 왕복이 늘어나요(병렬 도구 사용 비활성화). 배치 동작에 대한 나머지 계약은 컴퓨터 사용 도구에서 그대로 이어져요. 다음 사용자 메시지의 모든 tool_usetool_result가 하나씩 붙는 것까지요. 단 두 가지만 다릅니다. 하나는 정지 텍스트, 다른 하나는 성공 결과의 내용이 뭘 담는지예요. 결과 내용은 이 페이지의 멤버 도구(Member tools)를 따릅니다. new_tab, switch_tab, close_tab, list_tabs 결과는 텍스트나 이미지 없이 정확히 browser_state 블록 하나이고(탭 관리 결과), 다른 멤버의 결과는 텍스트나 이미지에 browser_state 블록을 추가할 수 있어요(다른 결과의 탭 맥락). 배치 안에서 캐시 중단점이 어디에 적용되는지는 컴퓨터 사용 도구의 도구 파라미터 문서에 있는 cache_control 행에서 설명합니다.

대상과 좌표 (Targets and coordinates)

위치에 작용하는 멤버 도구는 target 객체를 받는데, 이는 뷰포트 픽셀 좌표이거나 read_pagefind가 돌려준 요소 참조예요. 멤버 도구 표에서 Target이라고 쓰는 파라미터는 두 형태 모두를 받아요.

Shape target.type Fields Accepted by
CoordinateTarget "coordinate" x, y (integers, viewport pixels) left_click, right_click, middle_click, double_click, triple_click, hover, left_click_drag (from and target), left_mouse_down, left_mouse_up, mouse_move, scroll
RefTarget "ref" ref (an element reference such as "ref_2") left_click, right_click, middle_click, double_click, triple_click, hover, scroll_to, form_input, file_upload

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

스크린샷은 이미지 한도를 넘지 않아야 해요. API는 툴셋 이미지를 축소하지 않습니다. 모델의 이미지 크기 한도를 넘거나, 요청이 이미지 20개를 넘을 때 적용되는 더 엄격한 이미지당 한도를 넘는 스크린샷·확대 이미지는 거부돼요. 돌려주기 전에 크기를 조정하고, 디스패치하기 전에 Claude의 좌표를 조정 비율의 역수로 다시 키우세요(이미지 한도에 맞게 스크린샷 크기 조정).

요소 참조는 read_pagefind에서 나옵니다. 두 출력의 각 요소는 빠른 시작 결과에서처럼 [ref_2] 같은 태그를 달고 있어요:

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

Claude는 나중에 클릭·호버·scroll_to·form_input·file_upload 호출에서 {"type": "ref", "ref": "ref_2"} target으로 참조를 다시 넘기거나, read_pageref 파라미터로 하위 트리를 읽어요. 여러분의 실행기가 참조를 할당하고, 각 참조에서 기본 노드(접근성 노드 ID, 저장된 셀렉터 등)로의 매핑을 유지하며, 참조가 되돌아오면 그 노드에 작용합니다.

참조는 그것을 만들어낸 탭으로 범위가 한정되고, 그 탭이 탐색하거나 DOM이 실질적으로 바뀌기 전까지 유효해요. API는 낡았거나 알 수 없는 참조를 감지할 수 없으므로, Claude가 실행기가 더 이상 알아보지 못하는 참조를 넘기면 Error: ref_3 is stale or not found on the current page. 같은 오류 결과를 돌려주세요. 그러면 Claude가 페이지를 다시 읽어 새 참조를 얻어요. 탭이 탐색하기 전에는 이미 나눠준 참조를 다시 번호 매기지 마세요. Claude가 아직 쥐고 있는 참조를 조용히 무효화시키기 때문이에요.

Claude는 두 목표 지정 스타일을 모두 쓰고 페이지가 드러내는 것에 따라 그 사이를 오갑니다. 여러분의 프롬프트와 실행기가 돌려주는 것이 선택을 이끌어요:

  • 쓸 만한 접근성 트리가 있는 페이지에서는 참조를 선호해요. 참조는 좌표 픽셀이 취약해지는 레이아웃 변경·리플로우에서도 살아남고, 포인터로 맞히기 어려운 컨트롤에도 Claude가 작용하게 해줘요.
  • 트리가 설명하지 못하는 콘텐츠는 좌표로 폴백해요. 캔버스 렌더링 인터페이스, 내장 영상이나 원격 데스크톱 표면, 가상화가 심한 목록, 크로스 오리진 iframe 안의 요소는 쓸 만한 노드가 없는 경우가 많아서, Claude는 스크린샷과 확대로 작업하고 좌표로 클릭합니다. 좌표가 어떤 프레임에 속하는지 해석하는 건 여러분의 실행기 몫이에요.
  • 읽기는 범위를 좁혀서, 스크린샷 전에 트리를 읽어요. 큰 페이지에서 read_pagefilter: "interactive"나 컨테이너의 ref를 쓰면 초점이 맞춰진 하위 트리가 돌아오고, 일반적인 페이지의 트리 읽기는 스크린샷보다 입력 토큰을 덜 쓰면서도 Claude가 즉시 작용할 수 있는 참조를 제공해요. 시각적 레이아웃, 이미지, 렌더링 상태가 중요할 때는 스크린샷이 여전히 올바른 관찰 수단입니다.

보안 고려사항 (Security considerations)

브라우저 사용은 일반 API 기능과 다른 위험을 갖고 있어요. Claude가 개방된 웹의 콘텐츠를 읽고 작용하는데, 어떤 페이지든 Claude를 조종하려고 쓴 텍스트를 담을 수 있기 때문입니다.

이런 위험을 줄이려면 다음과 같은 예방 조치를 취하세요:

  • 브라우저와 실행기를 최소 권한의 전용 컨테이너나 가상 머신에서 실행하고, 자격 증명이 없는 새 프로필을 사용하며, 민감한 파일시스템이나 내부 네트워크에는 접근할 수 없게 하세요. 함께 실행하는 다른 도구도 같은 방식으로 격리하세요.
  • 브라우저가 도달할 수 있는 호스트를 네트워크 계층에서 강제하는 도메인 허용 목록으로 제한하고, navigate 핸들러에서 리다이렉트 뒤에도 다시 확인하며, 작업이 필요하지 않으면 루프백·링크 로컬·사설 대역을 차단하세요.
  • 페이지가 주는 모든 것을 신뢰할 수 없는 입력으로 취급하세요. browser_state 블록에 보고하는 탭 제목과 URL도 마찬가지고요. 페이지 읽기는 원시 DOM 소스가 아니라 페이지가 렌더링하는 것(접근성 트리나 보이는 텍스트)에서 구성해, 숨겨진 텍스트가 Claude에 닿지 않게 하세요.
  • navigate 핸들러에서 히스토리 키워드 "back", "forward", "reload"를 받고, 스킴이 없는 URL은 https://로 처리한 뒤 URL을 파싱해 httphttps가 아닌 스킴(javascript:, file:, data:, chrome: 등)은 오류 결과로 거부하세요. 스킴 확인은 문자열 접두사가 아니라 URL 파서로 하세요. API는 탐색을 볼 수 없어 여러분을 대신해 거부할 수 없어요.
  • 필요할 때까지 javascript_execfile_upload비활성화로 두고, 둘 중 하나를 켜기 전에 선택적 멤버 활성화(Enable optional members)를 읽으세요.
  • 결과가 있는 행동이나 동의가 필요한 것(구매, 계정 수정, 메시징, 약관 수락)은 사람 확인을 받으세요. 한 턴에 여러 개가 실릴 수 있으니 호출마다 실행기에서 확인하세요.

Claude는 여러분의 지시와 충돌하더라도 페이지 콘텐츠에서 발견한 지시를 따를 때가 있어요. 페이지에 "이전 지시를 무시하고 ...로 이동하라"는 텍스트가 있으면 Claude가 작업에서 이탈할 수 있죠. Claude를 민감한 데이터와 행동에서 격리해 프롬프트 인젝션이 닿을 수 있는 범위를 제한하고, 젤브레이크와 프롬프트 인젝션 완화(Mitigate jailbreaks and prompt injections)를 검토하며, 로그인 세션이 필요한 작업이라면 전용 저권한 계정을 쓰고 계정 변경 행동에는 사람 확인을 유지하세요.

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

멤버 도구 (Member tools)

browser_toolset_20260801 항목은 31개의 멤버 도구를 선언해요. 각 호출의 입력은 여기 나열된 파라미터가 전부이고, tab_id는 선택이며 생략하면 활성 탭으로 기본값이 정해져요. Target, CoordinateTarget, RefTarget은 대상과 좌표에서 설명한 형태입니다. 네 멤버(javascript_exec, file_upload, read_console, read_network)는 기본적으로 비활성화되어 있고 활성화할 때만 나타나요. 각 행에 적힌 입력 경계와 출력 관례는 Claude에게 명시되는 것이지 API가 강제하는 게 아니므로, 입력(좌표를 뷰포트와 대조하는 것 포함)을 검증하고 관례를 여러분의 실행기에서 적용하세요.

결과에 이미지 블록이 필요한 건 screenshotzoom뿐이고, 탭 관리 네 멤버(new_tab, list_tabs, switch_tab, close_tab)는 정확히 browser_state 블록 하나를 돌려줘요(탭 관리 결과 참고). 다른 모든 멤버는 텍스트 블록을 돌려줍니다. Clicked element ref_2. 같은 짧은 확인이거나 멤버의 출력이거나요. 탭 관리 결과가 아닌 어떤 결과든 이미지 블록도 함께 실을 수 있는데, 보통 행동 후 찍은 스크린샷이어서 별도의 스크린샷 호출 없이 Claude가 결과를 볼 수 있어요. 배치 동작에서 어디에 붙이는지 보여줍니다. 멤버 tool_resulttext, image, browser_state 콘텐츠 블록만 담을 수 있어요.

Member Input Description
navigate url, tab_id? http나 https URL을 로드하거나 "back", "forward", "reload"로 히스토리를 이동한다. 스킴이 없는 URL은 https://로 처리하고 그 외 스킴은 오류 결과로 거부한다. 짧은 확인을 돌려주고, 탭의 URL이나 제목이 바뀌면 browser_state 블록도 함께 돌려준다.
screenshot tab_id? 뷰포트를 캡처해 이미지 블록을 돌려준다.
zoom region, tab_id? 작은 텍스트나 컨트롤을 자세히 보기 위해 region을 [x0, y0, x1, y1](뷰포트 픽셀)로 주고, 잘라내 확대한 이미지를 돌려준다.

포인터 (Pointer)

Member Input Description
left_click target: Target, modifiers?, tab_id? 좌표나 참조된 요소를 왼쪽 클릭한다. modifiers는 클릭 중 누르는 코드(chord)로, 예: "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? 참조된 요소가 보이도록 스크롤한다.

키보드와 타이밍 (Keyboard and timing)

Member Input Description
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) 동안 멈춘다.

페이지 읽기 (Page reading)

Member Input Description
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? 페이지의 보이는 텍스트를 일반 텍스트로 돌려주며 본문 기사 콘텐츠를 우선한다. 기사, 문서, 텍스트가 많은 페이지에 적합하다.

폼과 파일 (Forms and files)

Member Input Description
form_input target: RefTarget, value, tab_id? 폼 요소의 값을 직접 설정한다. value는 문자열, 숫자, 불리언이고, 체크박스에는 불리언을, select에는 옵션의 값이나 보이는 텍스트를 쓴다.
file_upload (기본 비활성화) target: RefTarget, paths?, document_ids?, tab_id? 실행기 파일시스템의 paths, 애플리케이션이 준비한 document_ids, 또는 둘 다로 파일 입력 요소의 파일을 설정한다. 최소 하나는 필수. 파일 업로드(Upload files) 참고.

진단과 스크립팅 (Diagnostics and scripting)

Member Input Description
read_console (기본 비활성화) tab_id? 마지막 읽기 이후 누적된 탭의 콘솔 항목(log, warning, error 줄)을 항목당 한 줄로 돌려준다. 콘솔·네트워크 활동 읽기 참고.
read_network (기본 비활성화) tab_id? 마지막 읽기 이후 탭의 네트워크 요청(method, URL, status, MIME type, timing)을 항목당 한 줄로 돌려준다.
javascript_exec (기본 비활성화) text, tab_id? Page 컨텍스트에서 text를 JavaScript로 실행하고 마지막 표현식의 값을 텍스트로 돌려준다. 선택적 멤버 활성화 참고.

탭 관리 (Tab management)

Member Input Description
new_tab (없음) 탭을 열고 활성 탭으로 만든다.
list_tabs (없음) 탭 목록을 보고한다.
switch_tab tab_id (필수) tab_id를 활성 탭으로 만든다.
close_tab tab_id (필수) tab_id를 닫는다.

성공 시 각각은 텍스트나 이미지 없이 정확히 browser_state 블록 하나를 돌려줘요. 탭 관리 결과 참고.

툴셋 구성 (Configure the toolset)

type 외에 툴셋 항목은 configs, cache_control, allowed_callers를 받아요. 이 필드들이 컴퓨터 사용 툴셋과 공유하는 규칙은 클라이언트 툴셋(Client toolsets)에 나열되어 있고, 이 절은 브라우저 특유의 기본값을 다룹니다. configs는 멤버 이름을 키로 하는 객체이고, 각 멤버의 값은 두 필드를 받아요:

Field Default Meaning
enabled true, 단 네 선택적 멤버는 false 멤버를 Claude에 제공할지 여부.
defer_loading false 툴셋 정의를 도구 검색을 위해 연기할지 여부. 모든 활성화된 멤버에서 같은 값으로 해석되어야 한다. 네 선택적 멤버를 비활성화해 두면, 툴셋을 연기한다는 것은 나머지 27개에 설정한다는 뜻이다. 클라이언트 툴셋 참고.

멤버 도구 활성화/비활성화 (Enable or disable member tools)

configs에는 바꾸려는 멤버만 나열하세요. 생략한 멤버는 기본값을 유지합니다. 예를 들어 콘솔 읽기는 구현했지만 저수준 포인터·키 유지 제어는 하지 않는 실행기는 read_console을 켜고 세 멤버를 내려놓죠:

{
  "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가 절대 그 이름을 부르지 않는다는 보장은 아니므로, 실행기는 그래도 그런 호출을 오류 결과로 답해야 합니다.

다른 도구와 결합 (Combine with other tools)

브라우저 사용 도구는 같은 tools 배열에 여러분의 도구와 다른 Anthropic 제공 도구와 함께 선언할 수 있어요. 사용자 정의 도구가 멤버와 이름을 공유할 수 있는데(여러분의 navigate 등), toolset_name이 Claude의 호출을 구분해 주기 때문이에요. 다만 browser라는 이름의 다른 항목은 있을 수 없고, 요청에는 브라우저 툴셋 항목이 단 하나만 있을 수 있어요.

컴퓨터 사용 도구와 함께 선언할 수도 있어요. 툴셋이든 이전 컴퓨터 사용 도구 버전이든요. 둘은 각자의 좌표 프레임(여기선 뷰포트 픽셀, 저기선 데스크톱 스크린샷 픽셀)에서 독립적으로 동작하고, screenshot이나 key처럼 이름을 공유하는 멤버에 대한 Claude의 호출은 toolset_name으로 구분돼요.

선택적 멤버 활성화 (Enable optional members)

네 멤버 도구는 기본적으로 비활성화되어 있어요. javascript_execfile_upload는 조종된 페이지가 Claude로 하여금 할 수 있는 일을 넓히기 때문이고, read_consoleread_network는 모든 브라우저 자동화 스택이 그 로그를 제공할 수 없고 페이지가 제어하는 콘텐츠가 Claude에 닿는 범위를 넓히기 때문입니다. 각각은 실행기가 구현하고 작업이 필요할 때만 configs로 활성화하세요(예: "configs": {"file_upload": {"enabled": true}}).

파일 업로드 (Upload files)

file_upload<input type="file"> 요소의 파일을 직접 설정하는데, 네이티브 파일 선택기를 구동하는 것보다 더 안정적이에요. 그 target은 호출이 요소의 정체성을 필요로 하므로 참조만 받고, paths, document_ids, 또는 둘 다를 받아요:

  • paths는 실행기 파일시스템의 파일 경로로, 실행기가 여러분의 애플리케이션 파일을 직접 읽을 수 있는 배포를 위한 거예요(다운로드의 path를 채우는 조건과 같아요).
  • document_ids는 실행기가 그렇게 읽을 수 없을 때, 애플리케이션이 브라우저에 준비해 둔 파일의 식별자입니다. 애플리케이션이 식별자가 무엇을 의미하는지 정의하고, 해석 범위를 이 작업을 위해 준비된 파일로 path처럼 한정하세요.
{
  "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 실행 (Run JavaScript in the page)

javascript_exec는 Claude가 page 컨텍스트에서 쓴 표현식을 실행하고 마지막 표현식의 값을 텍스트로 돌려줘요. Claude는 return 문이 아니라 표현식을 씁니다. 코드는 페이지의 전체 권한으로 실행되는데, 쿠키, 저장소, same-origin 요청까지 포함해요. 자격 증명이 없는 세션에서만 멤버를 활성화하고, 보안 고려사항의 도메인 허용 목록을 유지하며, 돌려받은 값을 신뢰할 수 없는 입력으로 취급하고, Claude가 내는 코드를 기록하세요.

콘솔과 네트워크 활동 읽기 (Read console and network activity)

read_console는 탭의 콘솔 항목을, read_network는 탭의 네트워크 요청을 돌려주는데, 각각 그 탭의 이전 읽기 이후 누적된 것을 항목당 한 줄의 텍스트로 돌려줘요. 콘솔 줄은 log, warning, error 항목 중 하나를 실고, 네트워크 줄은 method, URL, status, MIME type, timing을 실어요. 항목은 브라우저 자동화가 탭에 붙은 순간부터만 존재하므로, 비어 있는 결과가 이미 열려 있던 탭에 트래픽이 없었다는 뜻은 아니에요.

이 멤버들은 Claude가 반복 스크린샷 없이 잘못 동작하는 페이지를 진단하게 해줘요(스피너 뒤의 실패한 요청, 죽은 버튼 뒤의 스크립트 오류). 콘솔·네트워크 항목은 페이지가 제어하며 요청 URL의 토큰 같은 비밀을 자주 담으므로, Claude의 컨텍스트에 넣고 싶지 않은 자격 증명형 값을 지우고 아주 긴 항목은 돌려주기 전에 잘라내세요.

browser_state로 탭 추적 (Track tabs with browser_state)

Claude는 탭을 tab_id로 부르고, 어떤 탭이 존재하는지의 진실된 원천은 여러분의 애플리케이션이며, 그 상태를 browser_state 콘텐츠 블록으로 보고해요. Claude는 이 블록을 직접 보지 않고, API가 그로부터 Claude가 읽는 텍스트를 렌더링합니다.

{
  "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는 호출 후 열려 있는 탭의 전체 목록이지 델타가 아니에요. 비어 있을 수도 있고, 비어 있지 않으면 정확히 한 항목이 "active": true를 달아요.
  • state_changes(여기엔 없음)는 호출의 부수효과를 보고해요. 호출이 열었고 끝날 때 여전히 열려 있는 각 탭의 tab_opened 항목(그 tab_id는 tabs에도 있어야 함), 그리고 download 이벤트가 포함됩니다. 보고할 게 없으면 필드를 생략하고, 빈 배열은 거부돼요.
  • 블록은 브라우저 멤버 호출에 답하는 결과에만, tool_result당 최대 한 번 보내고, is_error: true인 결과에는 절대 보내지 마세요. "보고할 탭 상태 없음"은 블록을 생략하는 것으로 표현합니다.
  • API는 tabs를 다음 두 절에서 설명하는 대로 Claude를 위한 텍스트로 렌더링하고, state_changes의 download 항목은 검증만 되고 렌더링되진 않아요.

여러분이 tab_id 값을 할당해요. 자동화 라이브러리의 페이지 식별자든 여러분의 카운터든 어떤 안정적인 문자열이든 되는데, 그 식별자가 열려 있는 탭으로 이전 결과에 여전히 나열되어 있는 동안 같은 tab_id를 재사용하지 마세요. API는 이 블록에 다음 한도를 적용해요:

  • tab_id, title, url은 최대 4,096자, tab_id는 비어 있으면 안 되며, control 문자(개행 포함)나 유니코드 줄·문단 구분자를 담으면 안 돼요.
  • 블록은 최대 100개 탭과 200개 상태 변경을 나열할 수 있어요.
  • 같은 한도가 Claude가 switch_tabclose_tab에 넘기는 tab_id에도 적용돼요. API가 그것을 결과 텍스트로 렌더링하기 때문이라서, 한도를 위반하는 tab_id로 온 호출은 browser_state 블록 대신 오류 결과로 답하세요.

탭 제목과 URL은 페이지에서 오고 Claude가 읽는 텍스트로 렌더링되므로 프롬프트 인젝션 표면이에요. API는 URL을 그대로 렌더링하므로, tabs를 채우기 전에 페이지가 제공한 URL을 정화하세요. 제목의 큰따옴표와 백슬래시는 렌더링할 때 이스케이프하므로 제목을 미리 이스케이프하지 마세요(미리 이스케이프된 제목은 Claude에게 이중 이스케이프로 닿아요). 의심스러운 제목을 자르거나 버리는 건 여전히 가치 있어요. API가 강제하는 길이·문자 한도는 바닥이지 방어가 아니에요.

탭 관리 결과 (Tab management results)

new_tab, switch_tab, close_tab, list_tabs의 성공 결과 content는 텍스트나 이미지 없이 정확히 browser_state 블록 하나이고, API가 Claude가 보는 텍스트를 써요. new_tab 결과의 블록은 active: true로 표시된 항목과 tab_id가 일치하는 tab_opened 상태 변경을 정확히 하나 담아야 해요.

Member Text Claude sees
switch_tab Switched to tab {tab_id}, taken from the call's input.tab_id
close_tab Closed tab {tab_id}, taken from the call's input.tab_id
new_tab Created new tab with tab_id: {tab_id}, URL: {url}. It is now the current tab., taken from the entry marked active: true
list_tabs Available tabs: followed by one line per tab, or No tabs available when tabs is empty

첫 번째가 활성인 두 탭을 나열하는 list_tabs 결과는 다음과 같이 렌더링돼요. 각 줄은 두 칸 들여쓰고, 활성 탭에만 (current)가 붙습니다:

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(입력은 비어 있어요)을 부르면, 실행기는 탭을 열고 활성화하고 tab_opened 항목 하나가 든 목록을 돌려줘요:

{
  "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을 보고합니다.

다른 결과의 탭 맥락 (Tab context on other results)

다른 모든 멤버에서는 블록이 선택이에요. 열린 탭 집합, 활성 탭, 또는 탭의 제목·URL이 바뀌었거나 보고할 state_changes가 있을 때 보내고, 항상 전체 tabs 목록을 포함하세요. 결과가 텍스트와 browser_state 블록을 모두 실으면 API는 그 결과의 텍스트에 탭 맥락(Tab Context) 푸터를 빈 줄로 구분해 붙여서, Claude가 별도의 list_tabs 호출 없이 새 상태를 받아요:

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 결과.
  • 텍스트 블록이 없는 결과(이미지만 있는 스크린샷 결과 등). 그 결과에 대해 렌더링되거나 기억되는 건 없고, 탭 맥락은 텍스트와 browser_state 블록을 모두 실은 다음 결과에 나타나요. 같은 결과에서 탭 변경을 Claude가 보길 원하면 이미지 옆에 짧은 텍스트 블록을 포함하세요.
  • tab_id가 없는 호출에서 tabs 목록이 비어 있는 결과. 이름 붙일 탭이 없기 때문이에요.

예를 들어 Claude가 이 세션 앞에서 "Pricing" 링크(ref_5)를 클릭했을 때, 페이지가 그걸 Claude가 요청하지 않은 새 탭에서 열었다면, 보고가 없으면 Claude는 그걸 발견하려고 list_tabs를 불러야 해요. 클릭 확인과, 열린 탭을 state_changes에 이름 붙이고 실행기가 활성으로 둔 탭을 표시한 블록을 돌려주세요:

{
  "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_opened 항목을 얻지 못해요. 오류 결과는 browser_state를 실지 않기 때문이고, 대신 다음 성공 결과의 tabs 목록에 나타나요. 배치에서는 변경이 일어난 호출의 결과에 블록을 붙이고, 같은 턴의 이전 결과가 같은 상태를 보고했더라도 성공한 각 탭 관리 결과에 자기 블록을 주세요.

다운로드 보고 (Report downloads)

클릭이나 탐색이 파일 다운로드를 시작하면, 그것이 일어난 호출의 결과에서 state_changes로 보고하고, 여러분이 할당하는 download_id로 결과들을 연관지어요. 다운로드는 비동기로 실행되고 여러 결과에 걸칠 수 있으므로 세 가지 이벤트 유형이 있어요:

type Fields When to send
download_started download_id, url 다운로드가 시작된 호출의 결과에서. url은 리다이렉트 후 파일이 서빙되는 최종 URL.
download_completed download_id, url, path?, size_bytes? 다운로드가 끝난 뒤 실행 중인 어떤 이후 호출의 결과에서. path는 같은 환경의 다른 도구(예: bash 도구나 file_upload)가 그 파일을 읽을 수 있을 때만 포함하고, 아니면 download_id가 다운로드의 유일한 식별자.
download_failed download_id, url, error? 다운로드가 실패하거나 취소될 때. 브라우저가 제공하면 error에 이유.

API는 이 항목들을 검증하지만 Claude가 보는 텍스트로 렌더링하지는 않으므로, Claude가 파일에 작용해야 할 때는 같은 결과의 텍스트 블록에 파일 이름이나 경로도 함께 언급하세요.

예를 들어 Pricing 탭의 "Download price list (CSV)"(ref_8) 클릭이 다운로드를 시작하면, 그 클릭의 결과는 download_id "dl-1"과 파일 URL이 든 download_started 항목을 실어요. 다운로드는 나중의 스크린샷 호출이 실행되는 동안 끝나므로, 그 결과 content에는 이미지와 Screenshot captured. Download complete: /home/user/downloads/price-list.csv (48,213 bytes). 같은 텍스트 블록, 그리고 같은 download_id로 완료를 보고하는 이 browser_state 블록이 담겨요:

{
  "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
    }
  ]
}

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

  • 한 블록에서 download_id당 항목 최대 하나. 같은 호출에서 시작·완료된 다운로드는 download_completed만 보고한다.
  • is_error: true 결과에는 절대 state_changes를 보내지 않는다. 실패한 호출 중 발생한 다운로드 이벤트는 다음 성공 결과에 보고한다.
  • state_changes는 진행 중인 다운로드의 목록이 아니다. 각 이벤트를 한 번 보고한다.
  • 각 항목은 그 유형이 선언한 필드만 실어요. size_bytes는 음이 아닌 정수, download_id는 비어 있지 않아야 하며, download_id, url, path, error는 각각 최대 4,096자에 control 문자나 유니코드 줄·문단 구분자가 없어야 한다. url은 원격 서버에서 오고 리다이렉트 후 서명된 쿼리 문자열 자격 증명을 자주 담으므로, Claude의 컨텍스트에 넣고 싶지 않은 쿼리 파라미터를 제거하고 파일시스템 경로에 쓰거나 보고하기 전에 정화하세요.

오류 처리 (Handle errors)

실패한 호출을 Claude에게 일반 오류 결과로 보고하세요. is_error: true, 무슨 일이 있었는지 말하는 텍스트 content, toolset_name을 그대로, 그리고 browser_state 블록은 없이요.

실행기에서 오류 반환 (Return errors from your executor)

오류 텍스트를 구체적으로 만들면 Claude가 읽고 적응해요. Error: Navigation to https://example.com/status timed out after 30 seconds. The page may be unavailable.는 맨 Error: navigation failed보다 Claude가 작용할 거리를 줘요. 다른 일반적인 경우:

  • 거부된 탐색 스킴
  • 낡았거나 알 수 없는 요소 참조
  • 비활성화되었거나 구현되지 않은 멤버
  • 턴에서 앞선 실패 후 건너뜀

요청 오류 (Request errors)

API는 툴셋 항목과 대화의 모든 멤버 tool_use·tool_result 블록을 검증해요. 하나라도 형식이 잘못되면 Claude가 실행되기 전에 invalid_request_error를 돌려줍니다. 다음 표에서 왼쪽 열은 여러분이 보낸 것을 말해요.

Request Why it fails and what to do
툴셋 항목이 받아들이지 않는 옵션이나 조합. 예: 항목 자체의 name, strict: true, input_examples, defer_loading, 멤버 이름이 아닌 configs 키, 멤버 configs 값의 enabled·defer_loading 외 필드(툴셋 구성), defer_loading 값이 서로 다른 활성화된 멤버(툴셋 구성), 어떤 멤버도 활성화하지 않는 configs, allowed_callers의 코드 실행 호출자, 요청의 레거시 fine-grained-tool-streaming-2025-05-14 beta 헤더, browser나 멤버를 이름으로 하는 tool_choice, 두 번째 브라우저 툴셋 항목이나 browser라는 다른 도구 이들은 클라이언트 툴셋에서 지원되지 않는다. 각 규칙과 대안은 클라이언트 툴셋 참고.
"toolset_name": "browser" 없이 또는 다른 값으로 멤버 호출에 답하는 tool_result, 또는 멤버 호출이 아닌 결과의 toolset_name 멤버 결과에 toolset_name을 정확히 그대로 붙이고, 그런 결과에만 붙인다.
매칭되는 tool_result 없는 이전 턴의 멤버 tool_use 실패 후 실행하지 않은 호출을 포함해 모든 멤버 호출에 답한다.
멤버 결과의 text, image, browser_state 외 콘텐츠 블록 멤버 결과는 그 세 블록 타입만 받는다.
browser_state로 탭 추적의 규칙을 깨는 browser_state 블록. 예: is_error: true 결과나 브라우저 멤버 호출에 답하지 않는 결과의 블록, 결과당 하나 초과, active: true 항목이 정확히 하나 없는 비어있지 않은 tabs, 중복 tab_id, 빈 state_changes 배열, tabs에 없는 tab_id의 tab_opened, 한 download_id의 두 상태 변경 또는 유형이 선언하지 않은 상태 변경 필드(다운로드 보고), 한도 초과 필드 블록을 고친다. "보고할 것 없음"은 블록이나 state_changes 필드를 생략하는 것으로 표현하며, 빈 값으로는 절대 안 된다.
content가 정확히 browser_state 블록 하나가 아닌 성공한 new_tab·switch_tab·close_tab·list_tabs 결과, 또는 활성 탭과 일치하는 tab_opened가 정확히 하나 없는 new_tab 결과 API가 이 결과들을 블록에서 렌더링하므로 그 정확한 형태가 필요하다. 탭 관리 결과 참고.
모델 이미지 크기 한도, 또는 이전 결과의 스크린샷·확대 이미지를 세어 요청이 이미지 20개를 넘을 때 적용되는 더 엄격한 이미지당 한도를 넘는 결과의 이미지 API는 툴셋 이미지를 축소하지 않는다. 돌려주기 전에 스크린샷 크기를 조정하라(이미지 한도에 맞게 스크린샷 크기 조정).
browser_toolset_20260801을 지원하지 않는 모델 지원되는 모델은 호환성(Compatibility) 참고.

제한 사항 (Limitations)

  • 플랫폼 가용성: 브라우저 사용은 Claude API와 Google Cloud에서 사용할 수 있다.
  • 전체 입력 스트리밍만 지원: 스트리밍하면 각 멤버의 입력이 하나의 완전한 input_json_delta로 도착한다(클라이언트 툴셋).
  • 요소 참조는 최선 노력: 매우 동적인 페이지(가상화 목록, 캔버스 렌더링 인터페이스, 스크롤 시 다시 렌더링되는 페이지)는 안정적인 참조를 노출하지 못할 수 있고, Claude는 거기서 스크린샷과 좌표 클릭으로 폴백한다.
  • read_console과 read_network는 브라우저 자동화에 의존: 그것이 캡처할 수 있는 것만, 그것이 탭에 붙은 순간부터만 보고한다.
  • 일반 에이전트 제한 적용: 지연 시간, 시각 정확도, 프롬프트 인젝션 위험은 컴퓨터 사용 도구에서 이어진다(컴퓨터 사용 도구의 제한 사항 참고). 프롬프트로 모델 성능 최적화, 스크린샷 기록 관리, 구현 모범 사례 따르기(행동 지연, 행동 검증, 기록)의 지침도 브라우저 실행기에 적용된다.

가격과 데이터 보존 (Pricing and data retention)

브라우저 사용은 표준 도구 사용 가격을 따릅니다. 브라우저 사용 도구를 쓸 때:

  • 툴셋 정의 오버헤드: browser_toolset_20260801을 기본 멤버로 선언하면 요청에 입력 토큰 약 6,600개가 더해져요(Claude Fable 5, Claude Mythos 5, Claude Opus 5, Claude Opus 4.8에서는 약 6,610, Claude Sonnet 5에서는 약 6,670). 이는 멤버 도구 정의와 도구 사용 시스템 프롬프트를 포함해요. 네 선택적 멤버를 모두 활성화하면 약 880토큰이 더해지고, configs로 멤버를 비활성화하면 그 수가 줄어요. 요청의 정확한 수는 응답 usage에 보고되고, 토큰 계산 엔드포인트로 미리 추정할 수 있어요.
  • 추가 토큰 소비:
  • 도구 결과로 돌려주는 스크린샷·확대 이미지. 이미지 입력으로 청구된다(비전 가격 참고).
  • Claude에게 돌려주는 텍스트 도구 결과. 접근성 트리, 페이지 텍스트, 콘솔·네트워크 항목 등.

브라우저 사용과 함께 컴퓨터 사용 도구, bash 도구, 텍스트 편집기 도구, 또는 여러분의 도구를 쓴다면, 그 도구들은 각각의 페이지에 문서화된 대로 자기 토큰 비용을 가져요.

브라우저 세션, 다운로드, 업로드된 파일은 여러분의 환경에 남아요. 여러분이 돌려주는 스크린샷, 페이지 텍스트, 탭 상태는 API 요청 콘텐츠의 일부로 표준 보존 정책이나, ZDR 약정이 있다면 그것을 따릅니다. 브라우저 사용 도구는 ZDR 적격입니다. 보존 기간과 기능별 적격성은 API와 데이터 보존(API and data retention) 참고.

다음 단계 (Next steps)

  • 컴퓨터 사용 도구: 작업이 브라우저를 벗어날 때 Claude에게 전체 데스크톱 제어를 준다. 그 구현 지침은 브라우저 실행기에도 적용된다.
  • 도구 호출 처리 (Handle tool calls): tool_result 블록을 형식화하고, 이미지와 오류를 돌려주고, 대화를 계속한다.
  • 도구 참조 (Tool reference): 클라이언트 툴셋과 그 밖의 모든 Anthropic 제공 도구를 버전·파라미터와 함께 살펴본다.

호환성 (Compatibility)

지원 모델: Fable 5 and 5.1, Mythos 5 and 5.1, Opus 4.8 and 5, Sonnet 5

지원 플랫폼: Claude API, Google Cloud