> ## 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.

# Fetch Examples

> Real-world examples for the Fetch API

## Fetch a Single Page

Extract content from any URL as clean Markdown:

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

  client = TinyFish()
  result = client.fetch.get_contents(
      urls=["https://example.com"],
      format="markdown",
  )

  page = result.results[0]
  print(f"Title: {page.title}")
  print(page.text)
  ```

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

  const client = new TinyFish();
  const result = await client.fetch.getContents({
    urls: ["https://example.com"],
    format: "markdown",
  });

  const page = result.results[0];
  console.log(`Title: ${page.title}`);
  console.log(page.text);
  ```

  ```bash cURL theme={null}
  curl -s -X POST https://api.fetch.tinyfish.ai \
    -H "X-API-Key: $TINYFISH_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"urls": ["https://example.com"], "format": "markdown"}'
  ```
</CodeGroup>

**Output:**

```json theme={null}
{
  "results": [
    {
      "url": "https://example.com",
      "final_url": "https://example.com/",
      "language": "en",
      "text": "This domain is for use in documentation examples without needing permission...",
      "format": "markdown"
    }
  ],
  "errors": []
}
```

## Batch Fetch

Fetch up to 10 URLs in a single request. Failed URLs appear in `errors[]` without affecting the rest:

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

  client = TinyFish()
  result = client.fetch.get_contents(
      urls=[
          "https://example.com",
          "https://httpbin.org/html",
          "https://nonexistent.invalid",
      ],
      format="markdown",
  )

  for page in result.results:
      print(f"OK: {page.url} → {page.text[:80]}")

  for err in result.errors:
      print(f"FAIL: {err.url} → {err.error}")
  ```

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

  const client = new TinyFish();
  const result = await client.fetch.getContents({
    urls: [
      "https://example.com",
      "https://httpbin.org/html",
      "https://nonexistent.invalid",
    ],
    format: "markdown",
  });

  for (const page of result.results) {
    console.log(`OK: ${page.url} → ${page.text.slice(0, 80)}`);
  }

  for (const err of result.errors) {
    console.log(`FAIL: ${err.url} → ${err.error}`);
  }
  ```

  ```bash cURL theme={null}
  curl -s -X POST https://api.fetch.tinyfish.ai \
    -H "X-API-Key: $TINYFISH_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "urls": [
        "https://example.com",
        "https://httpbin.org/html",
        "https://nonexistent.invalid"
      ],
      "format": "markdown"
    }'
  ```
</CodeGroup>

## Control Cache Freshness

Use `ttl` when you need to bound how old a cached page can be. Set `ttl` to `0` when you want a live fetch, or to a positive number of seconds to accept cached entries younger than that window.

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

  client = TinyFish()
  result = client.fetch.get_contents(
      urls=["https://example.com"],
      ttl=0,
  )
  print(result.results[0].text)
  ```

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

  const client = new TinyFish();
  const result = await client.fetch.getContents({
    urls: ["https://example.com"],
    ttl: 0,
  });
  console.log(result.results[0].text);
  ```

  ```bash cURL theme={null}
  curl -s -X POST https://api.fetch.tinyfish.ai \
    -H "X-API-Key: $TINYFISH_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"urls": ["https://example.com"], "ttl": 0}'
  ```
</CodeGroup>

## Detect Page Changes with Conditional Requests

Save a page's `etag`, then replay it on your next fetch to skip re-processing content that hasn't changed. Conditional requests are a stateless pass-through — Fetch doesn't store the validators for you.

**1. Bootstrap: fetch once and save the `etag`**

<CodeGroup>
  ```bash cURL theme={null}
  curl -s -X POST https://api.fetch.tinyfish.ai \
    -H "X-API-Key: $TINYFISH_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "urls": ["https://example.com"],
      "include_etag_and_last_modified": true
    }'
  ```
</CodeGroup>

**Output:**

```json theme={null}
{
  "results": [
    {
      "url": "https://example.com",
      "final_url": "https://example.com/",
      "text": "This domain is for use in documentation examples without needing permission...",
      "format": "markdown",
      "etag": "W/\"abc123\"",
      "last_modified": "Wed, 21 Oct 2015 07:28:00 GMT"
    }
  ],
  "errors": []
}
```

Save `etag` (or `last_modified`) somewhere durable, keyed by URL.

**2. Later: replay the `etag` to check for changes**

<CodeGroup>
  ```bash cURL theme={null}
  curl -s -X POST https://api.fetch.tinyfish.ai \
    -H "X-API-Key: $TINYFISH_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "urls": ["https://example.com"],
      "if_none_match": "W/\"abc123\"",
      "include_etag_and_last_modified": true
    }'
  ```
</CodeGroup>

<Tabs>
  <Tab title="Unchanged">
    The origin confirms nothing changed — skip re-processing:

    ```json theme={null}
    {
      "results": [
        {
          "url": "https://example.com",
          "final_url": "https://example.com/",
          "text": null,
          "format": "markdown",
          "not_modified": true,
          "etag": "W/\"abc123\"",
          "last_modified": "Wed, 21 Oct 2015 07:28:00 GMT"
        }
      ],
      "errors": []
    }
    ```
  </Tab>

  <Tab title="Changed">
    The page changed — fresh content plus a new `etag` to save for next time:

    ```json theme={null}
    {
      "results": [
        {
          "url": "https://example.com",
          "final_url": "https://example.com/",
          "text": "This domain now includes updated documentation examples...",
          "format": "markdown",
          "etag": "W/\"def456\"",
          "last_modified": "Thu, 02 Jul 2026 12:00:00 GMT"
        }
      ],
      "errors": []
    }
    ```
  </Tab>
</Tabs>

## Extract Links

Get all hyperlinks and image URLs from a page:

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

  client = TinyFish()
  result = client.fetch.get_contents(
      urls=["https://www.tinyfish.ai/"],
      format="markdown",
      links=True,
      image_links=True,
  )

  page = result.results[0]
  print(f"Found {len(page.links)} links and {len(page.image_links)} images")

  for link in page.links[:5]:
      print(f"  → {link}")
  ```

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

  const client = new TinyFish();
  const result = await client.fetch.getContents({
    urls: ["https://www.tinyfish.ai/"],
    format: "markdown",
    links: true,
    image_links: true,
  });

  const page = result.results[0];
  console.log(`Found ${page.links.length} links and ${page.image_links.length} images`);

  for (const link of page.links.slice(0, 5)) {
    console.log(`  → ${link}`);
  }
  ```

  ```bash cURL theme={null}
  curl -s -X POST https://api.fetch.tinyfish.ai \
    -H "X-API-Key: $TINYFISH_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "urls": ["https://www.tinyfish.ai/"],
      "format": "markdown",
      "links": true,
      "image_links": true
    }'
  ```
</CodeGroup>

## Fetch as HTML

Get semantic HTML instead of Markdown — useful for preserving structure:

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

  client = TinyFish()
  result = client.fetch.get_contents(
      urls=["https://httpbin.org/html"],
      format="html",
  )

  page = result.results[0]
  print(page.text[:300])
  ```

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

  const client = new TinyFish();
  const result = await client.fetch.getContents({
    urls: ["https://httpbin.org/html"],
    format: "html",
  });

  const page = result.results[0];
  console.log(page.text.slice(0, 300));
  ```

  ```bash cURL theme={null}
  curl -s -X POST https://api.fetch.tinyfish.ai \
    -H "X-API-Key: $TINYFISH_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"urls": ["https://httpbin.org/html"], "format": "html"}'
  ```
</CodeGroup>

***

## Related

<CardGroup cols={2}>
  <Card title="Fetch Reference" icon="bolt" href="/fetch-api/reference">
    Full parameter, response, and content type docs
  </Card>

  <Card title="Search Examples" icon="magnifying-glass" href="/search-api/examples">
    Web search with geo-targeting
  </Card>
</CardGroup>
