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

# Web Scraping

> Extract data from any website using natural language

## Basic Example

Extract product data from any page:

<CodeGroup>
  ```python Python theme={null}
  from tinyfish import TinyFish, EventType, RunStatus

  client = TinyFish()

  with client.agent.stream(
      url="https://scrapeme.live/shop/Bulbasaur/",
      goal="Extract the product name, price, and stock status. Return as JSON.",
  ) as stream:
      for event in stream:
          if event.type == EventType.COMPLETE and event.status == RunStatus.COMPLETED:
              print("Result:", event.result_json)
  ```

  ```typescript TypeScript theme={null}
  import { TinyFish, EventType, RunStatus } from "@tiny-fish/sdk";

  async function main() {
    const client = new TinyFish();

    const stream = await client.agent.stream({
      url: "https://scrapeme.live/shop/Bulbasaur/",
      goal: "Extract the product name, price, and stock status. Return as JSON.",
    });

    for await (const event of stream) {
      if (event.type === EventType.COMPLETE && event.status === RunStatus.COMPLETED) {
        console.log("Result:", event.result);
      }
    }
  }

  main();
  ```

  ```bash cURL theme={null}
  curl -N -X POST https://agent.tinyfish.ai/v1/automation/run-sse \
    -H "X-API-Key: $TINYFISH_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://scrapeme.live/shop/Bulbasaur/",
      "goal": "Extract the product name, price, and stock status. Return as JSON."
    }'
  ```

  ```bash CLI theme={null}
  tinyfish agent run "Extract the product name, price, and stock status. Return as JSON." \
    --url scrapeme.live/shop/Bulbasaur/ --pretty
  ```
</CodeGroup>

**Output:**

```json theme={null}
{
  "name": "Bulbasaur",
  "price": "£63.00",
  "inStock": true
}
```

## Extract Multiple Items

Get all products from a category page:

<CodeGroup>
  ```python Python theme={null}
  from tinyfish import TinyFish

  client = TinyFish()

  with client.agent.stream(
      url="https://scrapeme.live/shop/",
      goal="Extract all products on this page. For each product return: name, price, and link. Return as JSON.",
  ) as stream:
      for event in stream:
          print(event)
  ```

  ```typescript TypeScript theme={null}
  import { TinyFish } from "@tiny-fish/sdk";

  async function main() {
    const client = new TinyFish();

    const stream = await client.agent.stream({
      url: "https://scrapeme.live/shop/",
      goal: "Extract all products on this page. For each product return: name, price, and link. Return as JSON.",
    });

    for await (const event of stream) {
      console.log(event);
    }
  }

  main();
  ```

  ```bash cURL theme={null}
  curl -N -X POST https://agent.tinyfish.ai/v1/automation/run-sse \
    -H "X-API-Key: $TINYFISH_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://scrapeme.live/shop/",
      "goal": "Extract all products on this page. For each product return: name, price, and link. Return as JSON."
    }'
  ```
</CodeGroup>

**Output:**

```json theme={null}
{
  "products": [
    { "name": "Bulbasaur", "price": "£63.00", "link": "https://..." },
    { "name": "Ivysaur", "price": "£87.00", "link": "https://..." },
    { "name": "Venusaur", "price": "£105.00", "link": "https://..." }
  ]
}
```

## Use Stealth Mode

For sites with bot protection:

<CodeGroup>
  ```python Python theme={null}
  from tinyfish import TinyFish, BrowserProfile

  client = TinyFish()

  with client.agent.stream(
      url="https://protected-site.com",
      goal="Extract product data",
      browser_profile=BrowserProfile.STEALTH,
  ) as stream:
      for event in stream:
          print(event)
  ```

  ```typescript TypeScript theme={null}
  import { TinyFish, BrowserProfile } from "@tiny-fish/sdk";

  async function main() {
    const client = new TinyFish();

    const stream = await client.agent.stream({
      url: "https://protected-site.com",
      goal: "Extract product data",
      browser_profile: BrowserProfile.STEALTH,
    });

    for await (const event of stream) {
      console.log(event);
    }
  }

  main();
  ```

  ```bash cURL theme={null}
  curl -N -X POST https://agent.tinyfish.ai/v1/automation/run-sse \
    -H "X-API-Key: $TINYFISH_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://protected-site.com",
      "goal": "Extract product data",
      "browser_profile": "stealth"
    }'
  ```
</CodeGroup>

## Use Proxy

Route through a specific country:

<CodeGroup>
  ```python Python theme={null}
  from tinyfish import TinyFish, BrowserProfile, ProxyConfig, ProxyCountryCode

  client = TinyFish()

  with client.agent.stream(
      url="https://geo-restricted-site.com",
      goal="Extract data",
      browser_profile=BrowserProfile.STEALTH,
      proxy_config=ProxyConfig(enabled=True, country_code=ProxyCountryCode.US),
  ) as stream:
      for event in stream:
          print(event)
  ```

  ```typescript TypeScript theme={null}
  import { TinyFish, BrowserProfile, ProxyCountryCode } from "@tiny-fish/sdk";

  async function main() {
    const client = new TinyFish();

    const stream = await client.agent.stream({
      url: "https://geo-restricted-site.com",
      goal: "Extract data",
      browser_profile: BrowserProfile.STEALTH,
      proxy_config: { enabled: true, country_code: ProxyCountryCode.US },
    });

    for await (const event of stream) {
      console.log(event);
    }
  }

  main();
  ```

  ```bash cURL theme={null}
  curl -N -X POST https://agent.tinyfish.ai/v1/automation/run-sse \
    -H "X-API-Key: $TINYFISH_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://geo-restricted-site.com",
      "goal": "Extract data",
      "browser_profile": "stealth",
      "proxy_config": {
        "enabled": true,
        "country_code": "US"
      }
    }'
  ```
</CodeGroup>

## Try It

<Steps>
  <Step title="Save the code">Save any example above as `scraper.ts`</Step>
  <Step title="Set your API key">`export TINYFISH_API_KEY="your_api_key" `</Step>
  <Step title="Run it">`npx tsx scraper.ts `</Step>
</Steps>

## Related

<CardGroup cols={2}>
  <Card title="Form Filling" icon="file-lines" href="/examples/form-filling">
    Automate form submissions
  </Card>

  <Card title="Run SSE API" icon="code" href="/api-reference">
    Complete API docs
  </Card>
</CardGroup>
