> ## Documentation Index
> Fetch the complete documentation index at: https://hyperbrowser.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# AI Function Calling

> Integrate Hyperbrowser scrape, crawl, and extract tools with OpenAI and Anthropic function calling

Hyperbrowser integrates seamlessly with OpenAI and Anthropic's function calling APIs, enabling you to enhance your AI applications with web scraping and crawling capabilities. This guide shows how to set up and use Hyperbrowser's scrape, crawl, and extract tools with OpenAI (and Anthropic-compatible definitions).

## Setup

### Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install @hyperbrowser/sdk dotenv openai
  ```

  ```bash yarn theme={null}
  yarn add @hyperbrowser/sdk dotenv openai
  ```

  ```bash pip theme={null}
  pip install hyperbrowser openai python-dotenv
  ```

  ```bash uv theme={null}
  uv add @hyperbrowser/sdk dotenv openai
  ```
</CodeGroup>

### Setup your Environment

To use Hyperbrowser with your code, you need an API Key from the [dashboard](https://app.hyperbrowser.ai). Add it to your `.env` as `HYPERBROWSER_API_KEY`. You will also need an `OPENAI_API_KEY`.

## Code

<CodeGroup>
  ```typescript Node.js theme={null}
  import OpenAI from "openai";
  import { Hyperbrowser } from "@hyperbrowser/sdk";
  import { WebsiteCrawlTool, WebsiteScrapeTool,WebsiteExtractTool } from "@hyperbrowser/sdk/tools";
  import { config } from "dotenv";

  config();

  // Initialize clients
  const hb = new Hyperbrowser({ apiKey: process.env.HYPERBROWSER_API_KEY });
  const oai = new OpenAI({
    apiKey: process.env.OPENAI_API_KEY,
  });

  async function handleToolCall(tc) {
    console.log("Handling tool call");

    try {
      const args = JSON.parse(tc.function.arguments);
      console.log(`Tool call ID: ${tc.id}`);
      console.log(`Function name: ${tc.function.name}`);
      console.log(`Function args: ${JSON.stringify(args, null, 2)}`);
      console.log("-".repeat(50));

      if (
        tc.function.name === WebsiteCrawlTool.openaiToolDefinition.function.name
      ) {
        const response = await WebsiteCrawlTool.runnable(hb, args);
        return {
          tool_call_id: tc.id,
          content: response,
          role: "tool",
        };
      } else if (
        tc.function.name === WebsiteScrapeTool.openaiToolDefinition.function.name
      ) {
        const response = await WebsiteScrapeTool.runnable(hb, args);
        return {
          tool_call_id: tc.id,
          content: response,
          role: "tool",
        };
      } else if (
        tc.function.name === WebsiteExtractTool.openaiToolDefinition.function.name
      ) {
        const response = await WebsiteExtractTool.runnable(hb, args);
        return {
          tool_call_id: tc.id,
          content: response,
          role: "tool",
        };
      } else {
        return {
          tool_call_id: tc.id,
          content: "Unknown tool call",
          role: "tool",
        };
      }
    } catch (e) {
      console.error(e);
      return {
        role: "tool",
        tool_call_id: tc.id,
        content: `Error occurred: ${e}`,
      };
    }
  }

  const messages = [
    {
      role: "user",
      content: "What does Hyperbrowser.ai do? Provide citations.",
    },
  ];

  async function openaiChat() {
    while (true) {
      const resp = await oai.beta.chat.completions.parse({
        model: "gpt-4o-mini",
        messages: messages,
        tools: [
          WebsiteCrawlTool.openaiToolDefinition,
          WebsiteScrapeTool.openaiToolDefinition,
          WebsiteExtractTool.openaiToolDefinition,
        ],
      });

      const choice = resp.choices[0];
      messages.push(choice.message);

      if (choice.finish_reason === "tool_calls") {
        for (const tc of choice.message.tool_calls) {
          const result = await handleToolCall(tc);
          messages.push(result);
        }
      } else if (choice.finish_reason === "stop") {
        console.log(choice.message.content);
        break;
      } else {
        throw new Error("Unknown Error Occurred");
      }
    }
  }

  openaiChat();
  ```

  ```python Python theme={null}
  import json
  import os

  from hyperbrowser import Hyperbrowser
  from hyperbrowser.tools import WebsiteCrawlTool, WebsiteScrapeTool, WebsiteExtractTool

  from openai import OpenAI
  from openai.types.chat import (
      ChatCompletionMessageToolCall,
      ChatCompletionMessageParam,
      ChatCompletionToolMessageParam,
  )
  from dotenv import load_dotenv

  load_dotenv()

  oai = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
  hb = Hyperbrowser(api_key=os.getenv("HYPERBROWSER_API_KEY"))


  def handle_tool_call(
      tc: ChatCompletionMessageToolCall,
  ) -> ChatCompletionToolMessageParam:
      print("Handling tool call")

      try:
          args = json.loads(tc.function.arguments)
          print(f"Tool call ID: {tc.id}")
          print(f"Function name: {tc.function.name}")
          print(f"Function args: {args}")
          print("-" * 50)
          if (
              tc.function.name
              == WebsiteCrawlTool.openai_tool_definition["function"]["name"]
          ):
              response = WebsiteCrawlTool.runnable(hb, args)
              return {"tool_call_id": tc.id, "content": response, "role": "tool"}
          elif (
              tc.function.name
              == WebsiteScrapeTool.openai_tool_definition["function"]["name"]
          ):
              response = WebsiteScrapeTool.runnable(hb, args)
              return {"tool_call_id": tc.id, "content": response, "role": "tool"}
          elif (
              tc.function.name
              == WebsiteExtractTool.openai_tool_definition["function"]["name"]
          ):
              response = WebsiteExtractTool.runnable(hb, args)
              return {"tool_call_id": tc.id, "content": response, "role": "tool"}
          else:
              return {
                  "tool_call_id": tc.id,
                  "content": "Unknown tool call",
                  "role": "tool",
              }
      except Exception as e:
          print(e)
          return {"role": "tool", "tool_call_id": tc.id, "content": f"Error occurred: {e}"}


  messages: list[ChatCompletionMessageParam] = [
      {
          "role": "user",
          "content": "What does Hyperbrowser.ai do? Provide citations.",
      },
  ]

  while True:
      response = oai.beta.chat.completions.parse(
          messages=messages,
          model="gpt-4o-mini",
          tools=[
              WebsiteCrawlTool.openai_tool_definition,
              WebsiteScrapeTool.openai_tool_definition,
              WebsiteExtractTool.openai_tool_definition,
          ],
      )

      choice = response.choices[0]
      messages.append(choice.message)  # type: ignore
      if choice.finish_reason == "tool_calls":
          for tc in choice.message.tool_calls:  # type: ignore
              result = handle_tool_call(tc=tc)
              messages.append(result)

      elif choice.finish_reason == "stop":
          print(choice.message.content)
          break

      else:
          raise Exception("Unknown Error Occured")
  ```
</CodeGroup>

Hyperbrowser exposes a `WebsiteCrawlTool`, a `WebsiteScrapeTool`, and a `WebsiteExtractTool` to be used for OpenAI and Anthropic function calling. Each class provides a tool definition for both OpenAI and Anthropic that defines the schema which can be passed into the tools argument. Then, in the `handleToolCall`/`handle_tool_call` function, we parse the tool call arguments and dispatch the appropriate tool class `runnable` function based on the function name which returns the result of the scrape or crawl in formatted markdown.
