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

# Delays and selectors

> Handle JavaScript-heavy sites, lazy-loaded content, and dynamic elements by waiting before capture.

Many modern websites load content dynamically with JavaScript. Screenshotly provides several mechanisms to ensure content is fully rendered before capturing.

## Delay parameter

The `delay` parameter specifies how many milliseconds to wait after the page loads before taking the screenshot (0–10000):

<CodeGroup>
  ```javascript JavaScript SDK theme={null}
  const screenshot = await client.capture({
    url: 'https://example.com',
    delay: 3000 // wait 3 seconds
  });
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.screenshotly.dev/v1/capture \
    -H "X-API-Key: $SCREENSHOTLY_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://example.com",
      "options": { "delay": 3000 }
    }' \
    --output screenshot.png
  ```
</CodeGroup>

Use `delay` when:

* The page has animations that need to complete
* Content loads via JavaScript after the initial page load
* You need to wait for fonts or images to render

## Wait for selector

The `wait_for_selector` parameter waits for a specific DOM element to appear before capturing:

```javascript theme={null}
const screenshot = await client.capture({
  url: 'https://example.com/dashboard',
  wait_for_selector: '.dashboard-loaded'
});
```

This is more reliable than a fixed delay because it captures as soon as the element exists, rather than waiting an arbitrary amount of time.

## Element capture with `selector`

The `selector` parameter captures a specific element instead of the full page:

```bash theme={null}
curl -X POST https://api.screenshotly.dev/v1/capture \
  -H "X-API-Key: $SCREENSHOTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "options": {
      "selector": "#hero-section",
      "selector_scroll_into_view": true
    }
  }' \
  --output element.png
```

| Parameter                     | Type    | Default | Description                                       |
| ----------------------------- | ------- | ------- | ------------------------------------------------- |
| `selector`                    | string  | —       | CSS selector of the element to capture            |
| `selector_scroll_into_view`   | boolean | true    | Scroll the element into view before capturing     |
| `error_on_selector_not_found` | boolean | false   | Return a `422` error if the selector is not found |

<Note>
  `selector` and `wait_for_selector` serve different purposes: `selector` captures a specific element, while `wait_for_selector` waits for an element to appear before capturing the full page (or viewport).
</Note>

## Navigation control with `wait_until`

The `wait_until` parameter controls when the page is considered loaded:

| Value              | Description                                         |
| ------------------ | --------------------------------------------------- |
| `load` (default)   | Wait for the `load` event                           |
| `domcontentloaded` | Wait for `DOMContentLoaded` event (faster)          |
| `networkidle0`     | Wait until no network connections for 500ms         |
| `networkidle2`     | Wait until 2 or fewer network connections for 500ms |

```javascript theme={null}
const screenshot = await client.capture({
  url: 'https://example.com/spa',
  wait_until: 'networkidle0' // wait for all network activity to finish
});
```

You can also pass an array to wait for multiple conditions:

```json theme={null}
{
  "url": "https://example.com",
  "options": {
    "wait_until": ["load", "networkidle2"]
  }
}
```

## Combining options

You can use `delay`, `wait_for_selector`, and `wait_until` together. The API waits for navigation (`wait_until`), then for the selector (`wait_for_selector`), then applies the additional delay:

```javascript theme={null}
const screenshot = await client.capture({
  url: 'https://example.com/charts',
  wait_until: 'networkidle2',
  wait_for_selector: '.chart-container',
  delay: 1000 // extra second after element appears
});
```

<Tip>
  When capturing SPAs built with React, Vue, or Angular, use `wait_for_selector` targeting a container that only renders after data loads. This is more reliable than guessing a delay value.
</Tip>

## Timeouts

If the page takes too long to load or the selector never appears, the request will time out.

| Parameter            | Default | Range      | Description                                  |
| -------------------- | ------- | ---------- | -------------------------------------------- |
| `timeout`            | 60000   | 1000–90000 | Total timeout for the entire capture process |
| `navigation_timeout` | 30000   | 1000–30000 | Timeout specifically for page navigation     |

```javascript theme={null}
const screenshot = await client.capture({
  url: 'https://slow-site.example.com',
  wait_for_selector: '.content',
  timeout: 90000,           // 90 seconds total
  navigation_timeout: 30000 // 30 seconds for page load
});
```

<Warning>
  If the `wait_for_selector` element never appears on the page, the request will fail after the timeout period. Set `error_on_selector_not_found: true` to get a clear error, or ensure the selector matches an element that will exist.
</Warning>
