# Requests, pagination and errors

Send your API key in `Authorization: Bearer YOUR_API_KEY`. Each endpoint reference lists its JSON inputs, defaults, limits and accepted values. Start with its minimal example, then add filters. When a page says “provide at least one of”, a URL or another listed identifier is required even though each individual field is optional.

## Use familiar inputs

Use `location` for Google Maps area searches and Craigslist searches. Google Maps resolves the place itself; Craigslist resolves a city or region from its published regional directory and asks for clarification when a name is ambiguous. For Amazon seller products, pass a public `seller_url` containing `seller=` or `me=`.

For Vinted filtered search, copy a filtered catalogue URL into `url`. The API extracts search text, category, size, brand, colour, condition and material IDs. You can also supply `min_price` and `max_price`. For Mercari search, `url` accepts a filtered search URL; seller listings accept `filters_url` for brand, category, query and price filters. Conflicting URL and explicit filter values fail validation.

Use `limit` and `url` where listed as preferred inputs. Older names remain available under advanced and compatibility inputs. Supply one version of each input; conflicting aliases are rejected. Pagination styles retain their existing meanings.

Flight searches accept city names or airport codes and resolve them through the source site’s autocomplete service. Include a country or region when you need a particular city with a shared name. The resolved selections appear in `result.data.resolved_locations`. Flight searches require `depart_date` in `YYYY-MM-DD` format. Return dates cannot precede departure. Hotel discovery endpoints do not accept stay dates or occupancy, and their undated prices are not stay-specific quotes.

`instagram/hashtag-posts` retrieves hashtag posts. `tiktok/follower-count` retrieves follower statistics. Existing tagged-posts and followers routes remain compatible. Twitter routes resolve to X; X is the single catalogue identity. Diagnostic health echo is excluded from the public scraper catalogue.

## Find accepted filter values

Inspect `GET /v1/tasks/{task_key}` for the current input schema and credit cost. Use `GET /v1/tasks/{task_key}/options?parameter=amenities` to discover published option values and labels. Omit `parameter` to list parameters with known complete options. This route uses the same API-key authentication.

Options are not available for every filter. An empty `values` array with `source: "none"` does not mean that no filter values are supported. Inspect `reason` and the endpoint schema. For example, `options_not_confidently_complete` means no complete option list is published; `parameter_not_found` means the parameter name is unknown.

## Continue results

Pagination differs by endpoint. Use the fields listed in that endpoint’s reference: some accept `cursor`, others `after`, `offset`, or `pages`. `pages` is the number of pages fetched by one request, while `page` selects a starting page. Increasing these values can increase request time and the amount of data returned.

For endpoints returning `result.pagination.next_cursor`, pass that value unchanged as `cursor` on the next request. Keep the original search and filters unchanged and follow any endpoint-specific cursor expiry or limit restrictions. An empty filtered page can still have a next cursor. Do not invent a cursor for the first request.

For Reddit, pass `result.after` as `after` to move forward, or `result.before` as `before` to move backward. For Instagram profiles, pass `result.pagination.end_cursor` as `after` while `has_next_page` is true. For Airbnb reviews and host listings, pass `result.pagination.next_offset` as `offset`. Airbnb search accepts its returned `next_page_cursor` as `cursor`.

Endpoints exposing only `pages` fetch a bounded batch starting at their default first page. A continuation value in their output does not imply a reusable input unless the endpoint reference lists one. Keep page-count limits in mind when planning a larger collection.

## Download completed exports

Downloader results may initially contain only `export_id`. Poll the run until it succeeds to get the signed `download_url`, `download_url_expires_at` and `result_summary`. A `pending://` URL is a placeholder. For ZIP exports, inspect `status`, `truncated`, `failed_media` and file counts to distinguish a requested post cap from media failures. Download URLs expire separately from the stored artifact; request the run again while the artifact is retained to obtain a refreshed link.

## Handle invalid inputs

A schema validation failure returns HTTP 400 before starting a scraper run. The response identifies fields to correct:

```json
{
  "title": "Invalid request",
  "status": 400,
  "detail": "Request body failed validation against the task input schema.",
  "error_code": "validation_error",
  "retryable": false,
  "action": "check_input",
  "request_id": "req_example",
  "errors": [
    {
      "path": "limit",
      "message": "must be at most 100"
    }
  ]
}
```

Some input checks happen after a run starts. Those failures appear in the run’s `error` object and may provide less field detail. Inspect `error.code`, `error.message`, `error.retryable` and `error.action`.

## Wait for a run and retry safely

HTTP success means the request was accepted; it does not guarantee successful extraction. Check `run_status`. Poll `status_url` while the run is queued or running, using exponential backoff. Read `result` after `succeeded`. For `failed`, inspect `error`. Keep the run ID and request ID when contacting support.

For a pending run, poll its existing status URL instead of submitting another scrape. Honor `Retry-After` on HTTP 429. A failed run with `error.retryable: true` may be retried as a new request; this creates another run. A false value means the input, account connection or another stated condition needs attention first.

## Retry without creating duplicate runs

For each new task execution, generate a unique `Idempotency-Key` header and keep it with the request body. If the connection times out before you receive a run ID, retry the same request with the same key and unchanged body. This lets the API return the saved run rather than start another scrape. Once you have a run ID, poll that run.

Reusing a key with different input returns `409 idempotency_conflict`. Use a new key for a genuinely new execution, including an intentional retry after a terminal failed run. Do not generate a fresh key just because a response was lost.

If HTTP 428 includes a `hosted_url`, open it to connect the required website account. Follow the returned status URL and authentication instructions. See [website logins](/docs/api/website-logins.md) .

---
Source: https://browsable-api-ux-staging.pages.dev/docs/api/request-guide
