API Documentation
Surfapi exposes a simple, stable JSON contract. Every request is a single GET to
/search.json with an engine and
query parameters; the response is JSON with search_metadata,
search_parameters, and the parsed results.
Already using a hosted search API? Point your client at
surf-api.com and use your Surfapi key —
the request parameters and response shapes are standard and well-documented below.
Authentication
Pass your API key as api_key in the query string, or as an
X-API-Key header.
curl "https://surf-api.com/search.json?engine=google_news&q=coffee&api_key=YOUR_API_KEY"
Sign up to get a key — your examples below will be pre-filled.
Endpoints
| Endpoint | Description |
|---|---|
GET /search.json | Run a search. Returns JSON. |
GET /search | Alias of /search.json. |
GET /account | Your plan, usage, and searches left. |
GET /searches/:t/:id.json | Retrieve an archived search. |
GET /engines | List available engines. |
Response format
Every successful request returns a single JSON object built from two metadata blocks plus one or more result arrays. The search_metadata block describes the request that ran, and search_parameters echoes the inputs you sent (the engine plus any engine-specific params).
| Field | Description |
|---|---|
search_metadata.id | Unique identifier for this search. |
search_metadata.status | "Success" when results are present. |
search_metadata.created_at | When the search was accepted. |
search_metadata.processed_at | When processing completed. |
search_metadata.total_time_taken | Total processing time in seconds. |
search_metadata.<engine>_url | The upstream URL that was fetched (e.g. google_url). |
search_metadata.json_endpoint | Permalink to this result as JSON. |
search_metadata.raw_html_file | Permalink to the captured raw HTML. |
search_parameters | The engine and all other params you sent, echoed back. |
The result array depends on the engine you call:
| Engine | Result key |
|---|---|
google | organic_results |
google_images | images_results |
google_news | news_results |
google_shopping | shopping_results |
google_hotels | properties |
google_hotels_autocomplete | suggestions |
google_flights | best_flights + other_flights |
Many engines return additional blocks alongside the primary array — for example google also includes related_searches, related_questions, answer_box, pagination and serpapi_pagination; google_hotels adds brands and ads; and google_flights adds price_insights and airports. The per-engine sections below document the fields of each.
Errors
Errors are returned as JSON with a matching HTTP status code. A failed request never counts against your quota — only successful searches are metered.
| Status | Meaning | When |
|---|---|---|
200 | Success | Results returned in the response envelope. |
401 | Unauthorized | The api_key is missing or invalid. |
402 | Quota reached | Your monthly search allowance is used up. |
422 | Unprocessable | The engine needs a backend or proxy that is not configured. |
429 | Rate limited | You exceeded the per-hour request limit for your plan. |
500 | Internal error | Something went wrong on our side; retry shortly. |
Every error uses the same shape:
{
"error": "Invalid API key."
}
Rate limits & quotas
Each plan has a monthly pool of searches and a per-hour request ceiling. Usage is metered per successful search: requests that return an error status (401, 402, 422, 429, 500) are not counted.
| Plan | Searches / month | Requests / hour |
|---|---|---|
| Free | 250 | 100 |
| Hobby | 2,000 | 400 |
| Starter | 10,000 | 1,000 |
| Pro | 30,000 | 2,000 |
| Business | 75,000 | 5,000 |
Check your live quota at any time with GET /account. It accepts the same authentication as the search endpoint and returns your plan and remaining balance:
// GET https://surf-api.com/account?api_key=YOUR_API_KEY { "plan_name": "Starter", "searches_per_month": 10000, "total_searches_left": 8412, "this_month_usage": 1588 }
Localization & pagination
Use gl and hl to localize results, and start with num to page through them on engines that support pagination.
| Param | Description |
|---|---|
gl | Two-letter country code for the result region (e.g. us, gb, de). |
hl | Two-letter language code for the interface language (e.g. en, fr, es). |
start | Result offset for pagination (e.g. 10 skips the first 10 results). |
num | Number of results to return per page. |
https://surf-api.com/search.json?engine=google&q=kaffee&gl=de&hl=de&start=10&num=10&api_key=YOUR_API_KEY
Quickstart in your language
The same request — a google_flights search from JFK to LHR — in four languages. Replace YOUR_API_KEY with your key.
cURL
curl "https://surf-api.com/search.json?engine=google_flights&departure_id=JFK&arrival_id=LHR&outbound_date=2026-07-10&return_date=2026-07-17&api_key=YOUR_API_KEY"
JavaScript (fetch)
const params = new URLSearchParams({ engine: "google_flights", departure_id: "JFK", arrival_id: "LHR", outbound_date: "2026-07-10", return_date: "2026-07-17", api_key: "YOUR_API_KEY" }); fetch("https://surf-api.com/search.json?" + params.toString()) .then(function (res) { return res.json(); }) .then(function (data) { console.log(data.best_flights); });
Python (requests)
import requests params = { "engine": "google_flights", "departure_id": "JFK", "arrival_id": "LHR", "outbound_date": "2026-07-10", "return_date": "2026-07-17", "api_key": "YOUR_API_KEY", } res = requests.get("https://surf-api.com/search.json", params=params) print(res.json()["best_flights"])
PHP (cURL)
$params = http_build_query([
"engine" => "google_flights", "departure_id" => "JFK", "arrival_id" => "LHR",
"outbound_date" => "2026-07-10", "return_date" => "2026-07-17", "api_key" => "YOUR_API_KEY",
]);
$ch = curl_init("https://surf-api.com/search.json?" . $params);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = json_decode(curl_exec($ch), true);
print_r($data["best_flights"]);
Google Search ● live, no proxy
Whole-web organic results in SerpApi-compatible shape: snippets, related searches, answer box, pagination. engine=google
Parameters
| Parameter | Description |
|---|---|
q required | Search query. |
location | Geographic location to originate the search from. |
google_domain | Domain, e.g. google.com (default). |
gl | Two-letter country code (default us). |
hl | Two-letter language code (default en). |
num | Number of results. |
start | Result offset for pagination. |
Response — organic_results[]
| Field | Description |
|---|---|
position | Rank of the result on the page (1-based). |
title | Result title. |
link | Destination URL (real publisher link). |
displayed_link | Breadcrumb-style URL shown by Google. |
redirect_link | Google /url redirect wrapper for the link. |
snippet | Result description / excerpt. |
source | Result domain. |
sitelinks | Inline sub-links when present ({ inline: [...] }). |
Also returns related_searches, related_questions, answer_box and knowledge_graph (when present), plus pagination and serpapi_pagination.
# cURL curl "https://surf-api.com/search.json?engine=google&q=coffee&gl=us&hl=en&api_key=YOUR_API_KEY"
Google Images ● live, no proxy
Image results with thumbnails, source, and original URLs (no proxy required). engine=google_images
Parameters
| Parameter | Description |
|---|---|
q required | Search query. |
gl | Country code. |
hl | Language code. |
safe | Safe search: active or off. |
Response — images_results[]
| Field | Description |
|---|---|
position | Rank of the image (1-based). |
title | Image title. |
link | Page the image appears on. |
original | Direct URL of the full-size image. |
original_width / original_height | Full-size image dimensions in px. |
thumbnail | Thumbnail image URL. |
source | Host site of the image. |
# cURL curl "https://surf-api.com/search.json?engine=google_images&q=coffee&api_key=YOUR_API_KEY"
Google News ● live, no proxy
News articles and story clusters with sources and timestamps. engine=google_news
Parameters
| Parameter | Description |
|---|---|
q | Search query (omit for top headlines). |
gl | Country code. |
hl | Language code. |
Response — news_results[]
| Field | Description |
|---|---|
position | Rank of the article / cluster (1-based). |
title | Headline. |
link | Article URL. |
source | Publisher name. |
date | Publish timestamp. |
thumbnail | Article thumbnail when available. |
stories | Related articles in a story cluster (same fields). |
# cURL curl "https://surf-api.com/search.json?engine=google_news&q=coffee&api_key=YOUR_API_KEY"
Google Shopping ● needs residential proxy
Product listings with prices, ratings, sources, and thumbnails. engine=google_shopping
Parameters
| Parameter | Description |
|---|---|
q required | Search query. |
gl | Country code. |
hl | Language code. |
Response — shopping_results[]
| Field | Description |
|---|---|
position | Rank of the product (1-based). |
title | Product title. |
product_link | Link to the product. |
price | Displayed price string; extracted_price is the numeric value. |
source | Merchant / seller name. |
rating | Average rating; reviews is the review count. |
thumbnail | Product image URL. |
delivery | Delivery / shipping note when present. |
# cURL curl "https://surf-api.com/search.json?engine=google_shopping&q=coffee+maker&api_key=YOUR_API_KEY"
Google Hotels ● live, no proxy
Rich hotel listings (ratings, photos, tokens). With dates + currency, licensed bookable rates are merged in by name+geo. engine=google_hotels
Parameters
| Parameter | Description |
|---|---|
q required | Search query / city (or use property_token for details). |
check_in_date | YYYY-MM-DD — enables merged bookable rates. |
check_out_date | YYYY-MM-DD. |
currency | Convert merged rates (e.g. AED). |
adults | Number of adults. |
property_token | Fetch a single property’s details. |
Response — properties[]
| Field | Description |
|---|---|
name | Property name. |
type | hotel or vacation_rental. |
gps_coordinates | Latitude / longitude. |
rate_per_night / total_rate | Lowest nightly and total rate (with dates). |
prices | Per-source rates (with dates + currency). |
overall_rating | Average rating; reviews is the review count. |
amenities | List of amenities. |
images | Property photos. |
property_token | Token to fetch full details. |
Also returns brands, ads and serpapi_pagination. A property_token request returns a single property object.
# cURL curl "https://surf-api.com/search.json?engine=google_hotels&q=Bali+Resorts&api_key=YOUR_API_KEY"
Google Hotels Autocomplete ● live, no proxy
Typeahead suggestions resolving to property tokens. engine=google_hotels_autocomplete
Parameters
| Parameter | Description |
|---|---|
q required | Partial hotel/location query. |
Response — suggestions[]
| Field | Description |
|---|---|
value | Suggested display text. |
type | Suggestion type (e.g. hotel, city). |
property_token | Token for a google_hotels details request. |
location | Location label for the suggestion. |
thumbnail | Thumbnail when available. |
# cURL curl "https://surf-api.com/search.json?engine=google_hotels_autocomplete&q=Hilton+Malta&api_key=YOUR_API_KEY"
Google Flights ● live, no proxy
Best and other flight options with prices, segments, and carbon estimates. engine=google_flights
Parameters
| Parameter | Description |
|---|---|
departure_id required | Departure airport code, e.g. JFK. |
arrival_id required | Arrival airport code, e.g. LHR. |
outbound_date required | YYYY-MM-DD. |
return_date | YYYY-MM-DD (round trip). |
type | 1 round trip (default), 2 one-way, 3 multi-city. |
adults | Number of adults. |
currency | Currency code, e.g. USD. |
Response — best_flights[]
| Field | Description |
|---|---|
price | Total price for the itinerary. |
total_duration | Total travel time in minutes. |
type | Round trip, one way, etc. |
carbon_emissions | Estimated CO₂ for the itinerary. |
airline_logo | Logo for the marketing carrier. |
departure_token | Token to fetch return legs / continue the booking flow. |
flights | Per-segment details: airline, flight_number, departure_airport, arrival_airport, duration, airplane, travel_class, legroom. |
Also returns other_flights (same shape), price_insights and airports.
# cURL curl "https://surf-api.com/search.json?engine=google_flights&departure_id=JFK&arrival_id=LHR&outbound_date=2026-07-10&return_date=2026-07-17&api_key=YOUR_API_KEY"
Hotelbeds Hotels ● live, no proxy
Licensed, bookable hotels with real dated rates, any currency, rate keys — enriched with photos, descriptions, address (SerpApi-shaped). engine=hotelbeds
Parameters
| Parameter | Description |
|---|---|
q required | City name (e.g. Dubai) — resolved to a destination. Or pass destination/hotel_codes. |
check_in_date required | YYYY-MM-DD. |
check_out_date required | YYYY-MM-DD. |
currency | Convert displayed rates (e.g. AED, USD). Booking stays in the native rate currency. |
adults | Adults per room (default 2). |
children | Children per room. |
rooms | Number of rooms (default 1). |
destination | Hotelbeds destination code (e.g. PMI) — alternative to q. |
hotel_codes | Comma-separated Hotelbeds hotel codes — alternative to q. |
Response — properties[]
| Field | Description |
|---|---|
name | Property name. |
type | Property type. |
gps_coordinates | Latitude / longitude. |
rate_per_night / total_rate | Lowest nightly and total rate in the requested currency. |
prices | Bookable rates with rate keys for booking. |
amenities | List of amenities. |
images | Property photos. |
property_token | Hotelbeds hotel code for a details request. |
# cURL curl "https://surf-api.com/search.json?engine=hotelbeds&q=Dubai&check_in_date=2026-08-01&check_out_date=2026-08-04&adults=2¤cy=AED&api_key=YOUR_API_KEY"