Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Searlo AI Answers API
description: Live search results as clean JSON. The search endpoints return Google results — web, images, news, video, shopping, maps, scholar, patents and the full results page with ads, People Also Ask and AI Overviews — plus AI answers (ChatGPT, Copilot, Gemini), rank checks, web data (scrape, crawl, map, extract) and account endpoints. Get a free API key with 3,000 credits (no card required) at https://dashboard.searlo.tech. Not affiliated with or endorsed by Google LLC or any other search engine. All trademarks belong to their owners.
version: 1.2.0
contact:
name: Searlo
url: https://searlo.tech
email: hello@searlo.tech
license:
name: Proprietary API — see https://searlo.tech/terms
servers:
- url: https://api.searlo.tech/api/v1
description: Production
security:
- ApiKeyAuth: []
- BearerAuth: []
tags:
- name: AI Answers
description: Answers and citations from ChatGPT, Microsoft Copilot and Gemini, as their users see them.
paths:
/search/ai/{engine}:
get:
tags:
- AI Answers
summary: An AI answer engine's answer and citations
description: 'The engine''s answer to the prompt, generated live, with the sources it cited: ChatGPT (8 credits), Microsoft Copilot (8), Gemini (4). Perplexity is paused (403 FEATURE_NOT_AVAILABLE, not charged). Answers are produced live (typically 10-30 s) and are non-deterministic. A repeat within about an hour is served from cache and billed at the full rate, unless cache=false. Identical requests in flight at the same moment are merged into one run, and each is billed. Structured output (`schema`) is not available on this GET endpoint. aimode and grok are switched off in production. Searlo is independent and not affiliated with OpenAI, Microsoft, Google or Perplexity.'
parameters:
- name: engine
in: path
required: true
schema:
type: string
enum:
- chatgpt
- perplexity
- copilot
- gemini
- name: q
in: query
required: true
schema:
type: string
minLength: 1
maxLength: 500
- name: gl
in: query
schema:
type: string
maxLength: 5
description: Best-effort country for the answer. On Copilot, gl and hl form the Bing market code (e.g. en-US).
- name: hl
in: query
schema:
type: string
maxLength: 5
description: The language to ask in.
- name: cache
in: query
schema:
type: boolean
default: true
description: false forces (and bills) a fresh answer.
- name: mode
in: query
schema:
type: string
maxLength: 20
description: Echoed in searchParameters.mode and part of the cache key; it does not change the answer.
- name: model
in: query
schema:
type: string
maxLength: 40
description: 'Accepted but not used: answers come from each engine''s default model.'
- name: html
in: query
schema:
type: boolean
default: false
description: 'Also return html, an HTML snapshot of the answer page, and pageUrl. Same credits. A snapshot request always runs the engine: it is never served from or written to the cache.'
responses:
'200':
description: Answer with citations
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
searchParameters:
type: object
additionalProperties: true
answer:
type: string
answerMarkdown:
type: string
citations:
type: array
items:
type: object
properties:
index:
type: integer
url:
type: string
title:
type: string
domain:
type: string
sources:
type: array
items:
type: string
description: Unique cited domains (share of voice).
citationPills:
type: array
items:
type: object
additionalProperties: true
description: Copilot's source pills; empty on the other engines.
related:
type: array
items:
type: string
model:
type: string
description: Empty on ChatGPT and Copilot.
threadUrl:
type:
- string
- 'null'
complete:
type: boolean
description: false when the answer was still streaming at the deadline. Incomplete answers are not cached.
via:
type: string
fetchedAt:
type: string
format: date-time
source:
type: string
cached:
type: boolean
html:
type: string
description: 'With html=true: the answer page as the browser held it when the answer was read (the rendered DOM; on Copilot, the answer frame''s document). Stylesheets and scripts stay linked.'
pageUrl:
type:
- string
- 'null'
description: 'With html=true: the page''s URL at that moment.'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/InsufficientCredits'
'429':
$ref: '#/components/responses/RateLimited'
'403':
description: FEATURE_NOT_AVAILABLE, the engine is switched off on this deployment (retryable false). Not charged.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: The engine returned something unusable (retryable). Refunded.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
operationId: getSearchAiByEngine
x-operation-id-source: derived
components:
responses:
RateLimited:
description: 'The account''s rate limit (code 4201), the API key''s own (code 4202) or the cap on searches in flight (code 4203, errorCode CONCURRENCY_LIMIT, Retry-After 1, X-Concurrency-Limit carries the cap). Wait Retry-After seconds. See also AT_CAPACITY / BUSY / VERIFIER_BUSY, a full lane rather than a limit reached. Never charged.
'
headers:
Retry-After:
schema:
type: integer
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
Unauthorized:
description: Missing, invalid or expired API key (code UNAUTHORIZED)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
BadRequest:
description: 'Invalid request (code VALIDATION_ERROR; errors lists the fields). Search endpoints also answer 400 PAGE_OUT_OF_RANGE (maxPage) and DATE_FILTER_UNAVAILABLE, with the name in errorCode. Never charged.
'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
InsufficientCredits:
description: 'Account balance too low to complete the request (code INSUFFICIENT_CREDITS). details gives required, available and shortfall; topUpUrl links to buying more.
'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
schemas:
ErrorResponse:
type: object
properties:
success:
type: boolean
example: false
code:
description: 'Stable machine-readable name of the failure. Strings: VALIDATION_ERROR, INVALID_JSON, INVALID_IDEMPOTENCY_KEY, CITY_LOCATION_UNAVAILABLE, UNKNOWN_LOCATION, INVALID_DOMAIN, UNAUTHORIZED, INSUFFICIENT_CREDITS, FORBIDDEN, FEATURE_NOT_AVAILABLE, API_KEY_SCOPE_FORBIDDEN, NOT_FOUND, IDEMPOTENCY_REQUEST_IN_PROGRESS, PAYLOAD_TOO_LARGE, QUERY_NOT_SERVED, COUNTRY_UNAVAILABLE, IDEMPOTENCY_KEY_REUSED, TARGET_NOT_ALLOWED, AT_CAPACITY, BUSY, VERIFIER_BUSY, INTERNAL_ERROR, UPSTREAM_UNAVAILABLE, UPSTREAM_RATE_LIMITED, WARMING, UPSTREAM_TIMEOUT, CREDIT_SYSTEM_UNAVAILABLE, REVIEWS_WITHHELD, SERVICE_UNAVAILABLE, UPSTREAM_FAILED. The rate-limit 429s use numbers: 4201 (account), 4202 (API key), 4203 (searches in flight). Some 4xx carry their name in errorCode instead (see errorCode). No error is charged.
'
oneOf:
- type: string
- type: integer
example: CITY_LOCATION_UNAVAILABLE
message:
type: string
description: For people; may be reworded. Branch on code.
retryable:
type: boolean
description: Whether the same request can succeed later.
retryAfterSec:
type: integer
description: Seconds to wait before a retry (also the Retry-After header).
errors:
type: array
description: Validation errors, one per field.
items:
type: object
properties:
field:
type: string
message:
type: string
suggestions:
type: array
items:
type: string
description: 'UNKNOWN_LOCATION: close matches.'
location:
type: string
description: 'CITY_LOCATION_UNAVAILABLE: the place the request named.'
errorCode:
type: string
description: 'The name on errors that carry it here instead of in code, so read code and fall back to errorCode: PAGE_OUT_OF_RANGE (with maxPage), DATE_FILTER_UNAVAILABLE, INVALID_REQUEST, PLACE_NOT_FOUND, TARGET_REFUSED (with targetStatus), TARGET_UNREACHABLE (with targetError), INSUFFICIENT_CREDITS on POST /extract. Also set with code on 4203 (CONCURRENCY_LIMIT), FEATURE_NOT_AVAILABLE, TARGET_NOT_ALLOWED, REVIEWS_WITHHELD and every 503.
'
retryAfter:
type: integer
description: Seconds to wait, on 429 4201 to 4203 and on a retryable 503.
maxPage:
type: integer
description: 'PAGE_OUT_OF_RANGE: the last page that can be served at this limit.'
targetStatus:
type: integer
description: 'TARGET_REFUSED: the site''s own HTTP status.'
targetError:
type: string
description: 'TARGET_UNREACHABLE: why the site could not be fetched.'
details:
type: object
description: 'INSUFFICIENT_CREDITS: required, available and shortfall.'
additionalProperties:
type: number
topUpUrl:
type: string
description: 'INSUFFICIENT_CREDITS: a link to buy more credits.'
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: x-api-key
description: 'API key from your Searlo dashboard, e.g. sk_.... Get a free key with 3,000 credits at https://dashboard.searlo.tech (no card required).
'
BearerAuth:
type: http
scheme: bearer
description: 'The same API key, sent as Authorization: Bearer sk_.... A bearer token that does not start with sk_ is read as a dashboard login token.
'
CseKeyParam:
type: apiKey
in: query
name: key
description: 'The Searlo API key as the key query parameter, where Google''s Custom Search JSON API takes its key. Used by /customsearch/v1 only.
'
externalDocs:
description: Full documentation
url: https://searlo.tech/docs