Skip to main content
GET
/
smartbrowse
/
runs
/
{id}
Poll a SmartBrowse run
curl --request GET \
  --url https://api.webscrape.ai/v1/smartbrowse/runs/{id} \
  --header 'X-API-Key: <api-key>'
{
  "status": "completed",
  "request_id": "req_aB3xY9Kp",
  "data": {
    "id": "k7Xb9dRmQ2p",
    "recipe_id": "m3Yc2tFvN8q",
    "pages_extracted": 123,
    "items_extracted": 123,
    "credits_used": 123,
    "created_at": "2023-11-07T05:31:56Z",
    "started_at": "2023-11-07T05:31:56Z",
    "completed_at": "2023-11-07T05:31:56Z",
    "error": "<string>",
    "result": {
      "pages": [
        {
          "items": [
            {}
          ]
        }
      ],
      "mode": "<string>",
      "drift": 123,
      "warnings": [
        "<string>"
      ]
    }
  },
  "credits_used": 0,
  "credits_remaining": 123
}
Poll a SmartBrowse run. Returns the run state, page and item counts so far, and — once the run is done — the extracted result. Cost: Free. Polling never bills.

Polling pattern

import requests, time

API = "https://api.webscrape.ai/v1"
HDR = {"X-API-Key": "wsg_live_..."}

def run_and_wait(recipe_id):
    env = requests.post(f"{API}/smartbrowse/recipes/{recipe_id}/run", headers=HDR).json()
    run_id = env["data"]["run_id"]

    while True:
        env = requests.get(f"{API}/smartbrowse/runs/{run_id}", headers=HDR).json()
        run = env["data"]
        print(run["run_status"], run["pages_extracted"], "pages")
        if run["run_status"] in ("completed", "failed"):
            return run
        time.sleep(2)

Result shape

When data.run_status === "completed", the extracted items are at data.result.pages[].items. Each items entry matches the recipe’s saved schema.
{
  "status": "completed",
  "data": {
    "id": "k7Xb9dRmQ2p",
    "recipe_id": "m3Yc2tFvN8q",
    "run_status": "completed",
    "pages_extracted": 3,
    "items_extracted": 87,
    "credits_used": 6,
    "result": {
      "pages": [
        {
          "items": [
            { "name": "Product A", "price": "$19.99" },
            { "name": "Product B", "price": "$29.99" }
          ]
        }
      ],
      "mode": "replay",
      "drift": 0.02,
      "warnings": []
    },
    "started_at": "2026-05-21T12:00:00Z",
    "completed_at": "2026-05-21T12:01:30Z",
    "created_at": "2026-05-21T12:00:00Z"
  },
  "credits_used": 0,
  "credits_remaining": 494,
  "request_id": "req_aB3xY9Kp"
}
data.credits_used is the run’s total credits (per-page accrual). The envelope’s outer credits_used is always 0 — polling itself is free.

Tips

  • data.result.drift (a number between 0 and 1) measures how much the page has changed since the recipe was authored. There’s no fixed “too high” cutoff — read it alongside data.items_extracted when deciding whether to re-author. See the SmartBrowse feature page.
  • data.result.warnings lists non-fatal issues (e.g. pagination stalled before reaching the configured limit).
  • For push delivery instead of polling, set up a webhook on the recipe from the dashboard.

Authorizations

X-API-Key
string
header
required

Generate from the dashboard. Format: wsg_live_<32 base62 chars>.

Path Parameters

id
string
required

Opaque run ID (~11 base62 chars).

Example:

"k7Xb9dRmQ2p"

Response

Run state returned.

status
enum<string>
required

Discriminator for the envelope variant.

Available options:
completed
request_id
string
required

Per-request id. Also returned as the X-Request-ID response header. Include it when reporting issues.

Example:

"req_aB3xY9Kp"

data
object
required
credits_used
integer
required

Always 0. Polling is free; the run's accrued credits are surfaced in data.credits_used.

Example:

0

credits_remaining
integer
required