{"openapi":"3.1.0","info":{"title":"websearchapi.ai","version":"1.0.0","description":"Web scraping, structured search, and screenshots on a credit-based API. One key, weighted and transparent billing. Only requests that reach the target and return HTTP 2xx/400/404/410 are billed; failures and rejected parameters are auto-refunded. Billed responses carry `x-credits-charged`, `x-credits-remaining` and `x-upstream-status`, plus `x-target-status`, `x-target-url`, `x-resolved-url`, `x-detected-waf` and `x-target-cookies` when known; errors use the `Error` schema."},"servers":[{"url":"/","description":"This deployment"}],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Authorization: Bearer <API_KEY>"},"apiKeyHeader":{"type":"apiKey","in":"header","name":"x-api-key","description":"x-api-key: <API_KEY>"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized","bad_request","not_found","method_not_allowed","insufficient_credits","rate_limited","upstream_error","internal_error"]},"message":{"type":"string"}},"required":["code","message"]}}},"Balance":{"type":"object","properties":{"total":{"type":"integer"},"grant":{"type":"integer"},"topup":{"type":"integer"},"nextExpiry":{"type":"string","format":"date-time","nullable":true}}}}},"paths":{"/v1/ai-search":{"post":{"summary":"Web search","description":"Google web search with optional page content. Errors use `{ \"error\": { \"code\", \"message\" } }` with upper-case codes (`INVALID_REQUEST`, `AUTH_ERROR`, `INSUFFICIENT_CREDITS` 403, `RATE_LIMIT_EXCEEDED`, `SEARCH_ERROR`). Cost: 10 credits per result page (up to 10 results a page) plus, with `includeContent`, the cost of fetching each result (1 credit per page, 6 when it needs rendering). Responses carry `X-Credits-Consumed` and `X-Credits-Remaining`. Also served unversioned at `POST /ai-search`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"query":{"type":"string","description":"Search query."},"maxResults":{"type":"integer","minimum":1,"maximum":100,"default":10},"includeContent":{"type":"boolean","default":false,"description":"Fetch each result page as markdown into `content`."},"country":{"type":"string","description":"Two-letter country code, e.g. `us`."},"language":{"type":"string","description":"Language code, e.g. `en`."},"timeframe":{"type":"string","enum":["hour","day","week","month","year"]},"safeSearch":{"type":"boolean","default":false},"website":{"type":"string","description":"Restrict results to one site."},"siteSearch":{"type":"string","description":"Alias of `website`."},"includeDomains":{"type":"array","items":{"type":"string"}},"excludeDomains":{"type":"array","items":{"type":"string"}},"exactTerms":{"type":"string","description":"Phrase every result must contain."},"excludeTerms":{"type":"string","description":"Comma-separated terms to exclude."},"fileType":{"type":"string","description":"e.g. `pdf`."}}}}}},"responses":{"200":{"description":"Search results.","content":{"application/json":{"schema":{"type":"object","properties":{"searchParameters":{"type":"object","description":"The request body as sent."},"organic":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"url":{"type":"string"},"description":{"type":"string"},"position":{"type":"integer"},"content":{"type":"string","description":"Present when `includeContent` is true."}}}},"pagination":{"type":"object"}}}}}}}}},"/v1/scrape":{"post":{"summary":"Scrape a page","description":"Fetch one URL as markdown (default), HTML or a screenshot. Errors use `{ \"error\": { \"code\", \"message\" } }` with upper-case codes (`INVALID_REQUEST`, `INVALID_URL`, `AUTH_ERROR`, `INSUFFICIENT_CREDITS` 403, `RATE_LIMIT_EXCEEDED`, `SCRAPE_ERROR`). Cost: 1 credit (6 when the page needs a rendered retry), 5 with `method: \"browser\"`, a browser option or a screenshot; `premiumProxy` makes those 10 and 25. Invalid values for the extended options (`premiumProxy` onward) answer 400 `INVALID_REQUEST`. Responses carry `X-Credits-Consumed` and `X-Credits-Remaining`. Also served unversioned at `POST /scrape`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","description":"http(s) URL to scrape."},"method":{"type":"string","enum":["auto","no-browser","browser","ai"],"default":"auto","description":"How the page is loaded. `auto`: without a browser (the page's own markdown, else its HTML converted), retried in a browser if the result is empty — 1 credit, 6 on a retry. `no-browser`: never opens a browser, JavaScript does not run — always 1 credit. `browser`: a real browser runs JavaScript — 5 credits. `ai` is the legacy name of `no-browser` and still works."},"retain_images":{"type":"boolean","default":false,"description":"Keep images in the markdown."},"returnFormat":{"type":"string","enum":["markdown","html","text","screenshot","pageshot"],"default":"markdown","description":"`text` is served as markdown."},"engine":{"type":"string","enum":["direct","browser","cf-browser-rendering"],"default":"direct","description":"`browser` and `cf-browser-rendering` render JavaScript."},"timeout":{"type":"number","description":"Seconds, 5–120 (values outside are clamped)."},"waitForSelector":{"type":"string","description":"CSS selector to wait for (enables rendering)."},"viewport":{"type":"object","properties":{"width":{"type":"integer"},"height":{"type":"integer"}}},"injectPageScript":{"type":"string","description":"JavaScript to run in the page (enables rendering)."},"proxy":{"type":"string","description":"Two-letter country code for the exit location."},"setCookie":{"type":"string","description":"Cookies for the target, e.g. `name=value; name2=value2`."},"locale":{"type":"string","description":"Sent as Accept-Language."},"dnt":{"type":"boolean","description":"Send a DNT: 1 header."},"premiumProxy":{"type":"boolean","default":false,"description":"Residential & mobile proxy pool for sites that block datacenter traffic. 10 credits, 25 with rendering."},"proxyRegion":{"type":"string","enum":["europe","asia","africa","oceania","northamerica","southamerica"],"description":"Exit from a continent. Requires `premiumProxy: true`."},"sessionId":{"type":"integer","minimum":0,"description":"Reuse the same exit IP across requests sharing this id."},"device":{"type":"string","enum":["desktop","mobile","tablet"],"default":"desktop","description":"User agent and viewport profile."},"waitUntil":{"type":"string","enum":["domcontentloaded","load","networkidle0","networkidle2"],"description":"When the browser treats the page as loaded (enables rendering)."},"waitMs":{"type":"integer","minimum":0,"maximum":35000,"description":"Extra wait after load, in milliseconds (enables rendering)."},"blockResources":{"type":"boolean","default":true,"description":"Skip images, CSS and fonts while rendering. `false` enables rendering with them loaded."},"browserActions":{"type":"array","description":"Browser steps run in order before capture (enables rendering), e.g. `{ \"Action\": \"Click\", \"Selector\": \"#more\" }`, `{ \"Action\": \"Fill\", \"Selector\": \"#q\", \"Value\": \"text\" }`, `{ \"Action\": \"Wait\", \"Timeout\": 1000 }`, `{ \"Action\": \"ScrollY\", \"Value\": 800 }`, `{ \"Action\": \"Execute\", \"Execute\": \"…\" }`.","items":{"type":"object","required":["Action"],"properties":{"Action":{"type":"string"}},"additionalProperties":true}},"screenshotSelector":{"type":"string","description":"Capture only this element (CSS selector); implies a screenshot."},"includeNetworkRequests":{"type":"boolean","description":"Return the requests the page made in `data.networkRequests` (enables rendering)."},"includeHeaders":{"type":"boolean","description":"Return the target's status code and response headers in `data.statusCode` / `data.headers`."},"httpMethod":{"type":"string","enum":["GET","POST"],"default":"GET","description":"Method sent to the target. POST carries `headers` and `body`; rendering works with GET only."},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Extra headers sent to the target."},"body":{"description":"Request body sent to the target (a string, or JSON that is serialized)."}}}}}},"responses":{"200":{"description":"Scraped page.","content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"integer","enum":[200]},"status":{"type":"integer","enum":[20000]},"data":{"type":"object","properties":{"title":{"type":"string"},"url":{"type":"string","description":"The requested URL."},"content":{"type":"string"},"usage":{"type":"object","properties":{"tokens":{"type":"integer"}}},"screenshot":{"type":"string","description":"Base64 PNG, for `screenshot` / `pageshot`."},"networkRequests":{"type":"array","items":{"type":"object"},"description":"With `includeNetworkRequests`."},"actionResults":{"type":"array","items":{"type":"object"},"description":"With `browserActions`: one entry per step (`action`, `index`, `success`, and `response` — what an `Execute` script returned)."},"statusCode":{"type":"integer","description":"Target status code, with `includeHeaders`."},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Target response headers, with `includeHeaders`."}}}}}}}}}}},"/v1/screenshot":{"get":{"summary":"Screenshot a page","description":"Headless-browser screenshot. Returns a JSON envelope with base64 image(s). Cost: 5 credits baseline (reconciled to exact).","parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string"}},{"name":"fullPage","in":"query","schema":{"type":"boolean"},"description":"Full-page capture."},{"name":"selector","in":"query","schema":{"type":"string"},"description":"Capture only this element."},{"name":"super","in":"query","schema":{"type":"boolean"}},{"name":"geoCode","in":"query","schema":{"type":"string"}},{"name":"device","in":"query","schema":{"type":"string","enum":["desktop","mobile","tablet"]}}],"responses":{"200":{"description":"Screenshot JSON (base64).","content":{"application/json":{}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Screenshot a page (JSON body)","responses":{"200":{"description":"Screenshot JSON."}}}},"/v1/plugin/{endpoint}":{"get":{"summary":"Call a plugin","description":"Call a site-specific plugin endpoint (e.g. `google/search`, `amazon/pdp`). Query parameters are forwarded as-is; credits are charged at the exact upstream cost.","parameters":[{"name":"endpoint","in":"path","required":true,"description":"Plugin path, may contain slashes, e.g. `google/search`.","schema":{"type":"string"}}],"responses":{"200":{"description":"Upstream plugin response."},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Call a plugin (JSON body)","description":"Same as GET; JSON body fields are merged with query parameters (query wins).","responses":{"200":{"description":"Upstream plugin response."}}}},"/v1/credits":{"get":{"summary":"Get credit balance","description":"Remaining credits for the authenticated organization. Free.","responses":{"200":{"description":"Balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Balance"}}}}}}}}}