---
title: "API Docs · Best AI Scraper"
description: "BestAIScraper extraction API reference: authentication, fields, JSON Schema, list extraction, errors and code examples."
canonical_url: "https://bestaiscraper.com/docs"
meta:
  "og:description": "BestAIScraper extraction API reference: authentication, fields, JSON Schema, list extraction, errors and code examples."
  "og:image": "https://bestaiscraper.com/og.png"
  "og:image:alt": "Best AI Scraper: find the right AI web scraper"
  "og:image:height": "630"
  "og:image:width": "1200"
  "og:title": "API Docs · Best AI Scraper"
  "twitter:image": "https://bestaiscraper.com/og.png"
---

> Index of every page on this site: [llms.txt](https://bestaiscraper.com/llms.txt)

# **API reference**

One endpoint, JSON in and out. Authenticate with the key from your [credit purchase](https://bestaiscraper.com/pricing).

## **Authentication**

Send your key as a bearer token. Keys start with `bas_`.

```
Authorization: Bearer bas_xxxxxxxxxxxxxxxxxxxxxxxx
```

## **POST /api/v1/extract**

Fetches `url` and returns the requested fields. Pass either `fields` (simple) or `schema` (a full JSON Schema). Set `many: true` to get a list of items back under `data.items`.

```
{
  "url": "https://example.com/products",      // required, http(s)
  "fields": {                                  // name → "type — description"
    "name": "string",
    "price": "number — price without currency",
    "tags": "string[]",
    "image": "url"
  },
  "many": true,                                // optional, default false
  "instructions": "Skip sponsored listings",   // optional, max 2000 chars
  "escalate": true                             // optional: re-run doubtful results on a stronger model
}
```

## **Field types**

When you send your own `schema`, it must use the JSON Schema subset the model supports: every object needs `"additionalProperties": false`, make fields nullable with `anyOf`, and leave out numeric constraints such as `minimum`/`maximum` and recursive schemas. Unsupported schemas return `400`. The simple `fields` form always produces a valid schema.  
  
Start a field description with one of `string`, `number`, `integer`, `boolean`, `url`, `string[]`, `number[]`. Anything after it is a hint for the model. Every field can come back as `null` when it isn't on the page, and values are never invented.

## **Response**

```
{
  "url": "https://example.com/products",
  "data": { "items": [{ "name": "…", "price": 19.99, "tags": ["…"], "image": "https://…" }] },
  "truncated": false,            // true if the page text exceeded the size limit
  "confidence": {                // per field, 0–1: probability the value is right
    "name": 0.98, "price": 0.95, "tags": 0.91, "image": 0.97
  },
  "escalated": false,            // true if verification triggered a re-run on the stronger model
  "usage": {
    "models": "claude-haiku-5-5+jev",
    "input_tokens": 8123,
    "output_tokens": 912,
    "credits": 3,
    "credits_remaining": 3997
  }
}
```

## **Confidence and escalation**

After extraction, every field is checked against the page: is the value actually there, is it the right field, is it reasonable, does it match the format? `confidence` is the lowest of those checks for each field. In list mode, each field is scored across all items. If any check fails, the page is re-extracted on a stronger model (costs more credits; set `escalate: false` to opt out). `confidence` is `null` if verification is temporarily unavailable.

## **GET /api/v1/me**

Returns your remaining balance.

```
{ "key_prefix": "bas_AbCdEf", "credits": 3997 }
```

## **Python example**

```
import os, requests

r = requests.post(
    "https://bestaiscraper.com/api/v1/extract",
    headers={"Authorization": f"Bearer {os.environ['BAS_KEY']}"},
    json={"url": "https://news.ycombinator.com/", "many": True,
          "fields": {"title": "string", "url": "url", "points": "number"}},
    timeout=120,
)
r.raise_for_status()
for item in r.json()["data"]["items"]:
    print(item["points"], item["title"])
```

## **Limits**

Pages are limited to 3 MB of HTML and about 100k characters of extracted text (longer pages are truncated and flagged). Up to 40 fields per request. Allow up to 90 seconds per request. JavaScript is not executed.

## **Errors**

`400`Invalid body, URL or schema.

`401`Missing or invalid API key.

`402`Not enough credits for this page. Top up on the pricing page.

`415`The URL isn't HTML, JSON or text.

`422`The model couldn't produce a result (for example, the output was too large). Credits are refunded.

`429`Rate limited. Retry after a few seconds.

`502`The target page failed to load, or the model is temporarily unavailable. Credits are refunded.

```json
{"@context":"https://schema.org","@graph":[{"@id":"https://bestaiscraper.com/#website","@type":"WebSite","description":"Independent comparisons of AI web scraping tools, plus a pay-as-you-go AI extraction API.","name":"Best AI Scraper","url":"https://bestaiscraper.com/","publisher":{"@id":"https://bestaiscraper.com/#identity"}},{"@id":"https://bestaiscraper.com/docs#webpage","@type":"WebPage","description":"BestAIScraper extraction API reference: authentication, fields, JSON Schema, list extraction, errors and code examples.","name":"API Docs","url":"https://bestaiscraper.com/docs","isPartOf":{"@id":"https://bestaiscraper.com/#website"},"potentialAction":[{"@type":"ReadAction","target":["https://bestaiscraper.com/docs"]}]},{"@id":"https://bestaiscraper.com/#identity","@type":"Organization","name":"Best AI Scraper","url":"https://bestaiscraper.com"}]}
```

## Sitemap

See the full [sitemap](https://bestaiscraper.com/sitemap.md) for all pages.
