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

# Extend API timeout

> Use `extendTimeout` to keep automations running beyond the default 10-minute timeout

## Recipe

<Note>
  Long-running automations are less reliable than smaller, retryable units of work. When possible, break your automation into smaller steps that can complete within the default timeout.
</Note>

This recipe shows how to extend timeout limits for long-running automations using [`extendTimeout`](/main/05-references/runtime-sdk-typescript/extend-timeout) (TypeScript) or [`extend_timeout`](/main/05-references/runtime-sdk-python/extend-timeout) (Python).

This example demonstrates processing a large list with delays between requests—common when scraping rate-limited websites page by page.

<CodeGroup dropdown>
  ```typescript TypeScript theme={null}
  import { extendTimeout } from "@intuned/runtime";
  import { BrowserContext, Page } from "playwright";

  interface Book {
    title: string;
    price: string;
    url: string;
  }

  export default async function handler(
    params: { maxPages?: number },
    page: Page,
    context: BrowserContext
  ) {
    const allBooks: Book[] = [];
    const maxPages = params.maxPages || 50;
    let currentPage = 1;

    await page.goto("https://books.toscrape.com/");

    while (currentPage <= maxPages) {
      console.log(`Processing page ${currentPage} of ${maxPages}...`);

      // Extract books from current page
      const bookElements = page.locator("article.product_pod");
      const count = await bookElements.count();

      for (let i = 0; i < count; i++) {
        const book = bookElements.nth(i);
        const title = await book.locator("h3 a").getAttribute("title");
        const price = await book.locator(".price_color").textContent();
        const bookUrl = await book.locator("h3 a").getAttribute("href");

        if (title && price && bookUrl) {
          allBooks.push({
            title,
            price: price.trim(),
            url: `https://books.toscrape.com/${bookUrl}`,
          });
        }
      }

      console.log(`Completed page ${currentPage}. Books collected: ${allBooks.length}`);

      // Extend timeout after completing this unit of work
      extendTimeout();

      // Check if there's a next page
      const nextButton = page.locator(".next a");
      const hasNext = (await nextButton.count()) > 0;

      if (!hasNext || currentPage >= maxPages) {
        break;
      }

      // Add delay between page requests to respect rate limits
      await new Promise(resolve => setTimeout(resolve, 10000));

      // Navigate to next page
      await nextButton.click();
      await page.waitForLoadState("networkidle");

      currentPage++;
    }

    console.log(`Total books collected: ${allBooks.length}`);
    return allBooks;
  }
  ```

  ```python Python theme={null}
  import asyncio
  from intuned_runtime import extend_timeout
  from playwright.async_api import Page, BrowserContext
  from typing import Any, Dict, List

  async def automation(page: Page, params: Dict[str, Any] = None, **_kwargs):
      all_books = []
      max_pages = params.get("max_pages", 50) if params else 50
      current_page = 1

      await page.goto("https://books.toscrape.com/")

      while current_page <= max_pages:
          print(f"Processing page {current_page} of {max_pages}...")

          # Extract books from current page
          book_elements = page.locator("article.product_pod")
          count = await book_elements.count()

          for i in range(count):
              book = book_elements.nth(i)
              title = await book.locator("h3 a").get_attribute("title")
              price = await book.locator(".price_color").text_content()
              book_url = await book.locator("h3 a").get_attribute("href")

              if title and price and book_url:
                  all_books.append({
                      "title": title,
                      "price": price.strip(),
                      "url": f"https://books.toscrape.com/{book_url}",
                  })

          print(f"Completed page {current_page}. Books collected: {len(all_books)}")

          # Extend timeout after completing this unit of work
          extend_timeout()

          # Check if there's a next page
          next_button = page.locator(".next a")
          has_next = await next_button.count() > 0

          if not has_next or current_page >= max_pages:
              break

          # Add delay between page requests to respect rate limits
          await asyncio.sleep(10)

          # Navigate to next page
          await next_button.click()
          await page.wait_for_load_state("networkidle")

          current_page += 1

      print(f"Total books collected: {len(all_books)}")
      return all_books
  ```
</CodeGroup>

## Understanding timeouts

1. **Default timeout prevents stuck Runs** — Each Run attempt times out after 600 seconds (10 minutes) by default, configurable via `requestTimeout`. This prevents stuck automations from wasting resources.

2. **extendTimeout() resets the timer** — Each call resets the countdown to the original `requestTimeout` value. Call it as many times as needed, up to a 6-hour maximum total duration per Run.

3. **Correct placement is critical** — Call `extendTimeout()` after completing each unit of work (a page, batch, or logical section). Each unit must finish within the original timeout. For automations requiring more than 6 hours, contact Intuned support.

## Related SDK methods

<CardGroup cols={2}>
  <Card title="extendTimeout (TypeScript)" icon="js" href="/main/05-references/runtime-sdk-typescript/extend-timeout">
    Reset the timeout in TypeScript
  </Card>

  <Card title="extend_timeout (Python)" icon="python" href="/main/05-references/runtime-sdk-python/extend-timeout">
    Reset the timeout in Python
  </Card>

  <Card title="Jobs configuration" icon="clock" href="/main/02-features/jobs-batched-executions">
    Configure requestTimeout and retry settings
  </Card>
</CardGroup>
