AnswerLineStart free

, SERP API · Google · Tutorials

Google search parameters: gl, hl, uule, num, start, tbs and safe, mapped to API fields

Google’s results change with a handful of URL parameters: gl (country), hl (interface language), uule (location), num and start (depth and offset), tbs (time and other filters) and safe (SafeSearch). Device is not a URL parameter but changes the page just as much.

Two request shapes

POST /v1/monitor/google (and the GOOGLE async task type) accepts one of two shapes. The request must contain either query with country, query with gl, or url.

Standard shape. You describe the search with fields:

{ "query": "running shoes", "country": "US", "hl": "en", "location": "New York,New York,United States", "device": "mobile", "pages": 2 }

URL shape. You pass a complete Google web search URL, and the API applies a fixed set of its parameters:

{ "url": "https://www.google.com/search?q=running+shoes&gl=us&hl=en&num=20&tbs=qdr:m" }

The URL must be an absolute http(s) URL on a Google web search host (such as google.com, google.co.uk or www.google.de), with the path /search and a non-empty q. Only q, gl, hl, uule, num, start, tbs and safe are applied; everything else is dropped. Use the URL shape when you need start, tbs or safe, which have no field in the standard shape, or when you already store Google URLs.

Mapping table

Google parameter Meaning Standard shape URL shape
q Query, operators included query (1 to 10,000 characters) q in the URL
gl Result country country or gl (ISO 3166-1 alpha-2) gl in the URL, or country to override
hl Interface language hl hl in the URL, or the hl field
uule Encoded location uule, or location by name uule in the URL
num Results per page pages (1 to 10) num, read as depth in whole pages of ten, max 10 pages
start Result offset none start in the URL
tbs Time range and other filters none tbs in the URL
safe SafeSearch none safe in the URL
tbm Vertical (news, images, …) none rejected; use POST /v1/monitor/google/news for news
(not a URL parameter) Device device device
lr, cr, filter, others Various none dropped

gl and country

gl sets the country Google serves results for. In this API, country and gl take the same ISO 3166-1 alpha-2 codes, gl is accepted in either case (us or US), and the country must be one the endpoint supports:

curl https://api.answerline.dev/v1/countries?model=google \
  -H "Authorization: Bearer $ANSWERLINE_API_KEY"

Send country or gl. Sending both with different values is a 400. In the URL shape, country is derived from the URL’s gl; pass country explicitly to override it or when the URL has no gl.

hl

hl is the interface language, as Google’s own codes: en, de, pt-BR. It is free-form and case-insensitive, and it overrides the language the API would derive from the country. That lets you capture, for example, English-language results pages in Germany (country: "DE", hl: "en"). For multilingual AI answer monitoring, see multilingual AI answers.

Google’s Custom Search API documented a separate lr parameter to restrict documents to a language; for Google web search URLs, this API drops lr.

uule and location

Country-level targeting is not enough when the results you care about depend on where the searcher is, such as the local pack. Google encodes a location in the uule parameter. This API gives you two ways to set it:

location and uule are mutually exclusive. Neither can be combined with url; in the URL shape, put uule in the URL. Send country alongside for the matching country. For the local use case, see local rank tracking and state-level AI answers.

num, start and pages

Google’s num once set results per page, up to 100. Search Engine Roundtable reported in September 2025 that &num=100 had stopped working and that this broke most Google rank trackers. Results now come in pages of about ten.

This API models depth as pages:

start is the offset of the first result, and only exists in the URL shape. According to Bright Data’s Google URL parameter reference (dated February 26, 2026; Google does not document it), start=0 is page 1, start=10 page 2 and start=20 page 3. Pages continue from start, so start=20&num=20 asks for two pages beginning at the third.

For most tracking, skip start and ask for pages: one request returns the top N pages with page numbers already attached. See rank tracking with batches and Google rank tracking API.

device

Google serves separate desktop and mobile results pages, so capture the one your audience sees. device accepts:

Value Page returned
desktop (default) Desktop SERP
ios Mobile SERP, as Safari on iPhone
android Mobile SERP, as Chrome on Android
mobile Alias for android

device works in both shapes.

tbs

tbs carries Google’s search tools filters, most often time ranges. Google does not document its values. Bright Data’s reference lists:

tbs value Filter
qdr:h Past hour
qdr:d Past 24 hours
qdr:w Past week
qdr:m Past month
qdr:y Past year
cdr:1,cd_min:01/01/2025,cd_max:12/31/2025 Custom date range

URL-encode the value when you build the URL. If a documented alternative works for you, prefer it: Google’s Refine Google searches help page documents before: and after: operators, which go in query. See Google search operators.

safe

safe controls SafeSearch filtering. Google’s Custom Search reference defined active (filter) and off (default) for its API, and Bright Data’s reference lists the same values for web search URLs. In this API, safe is only available in the URL shape.

Validation rules

The request schema allows no unknown fields. These cases are rejected:

Request Why
Neither query + country/gl nor url One of the three shapes is required
query and url together Mutually exclusive
url with location, uule or pages The URL owns those values
location and uule together Mutually exclusive
country and gl with different values Conflicting geography
A country not listed by GET /v1/countries?model=google Unsupported
A url that is not a Google web search URL with path /search and a non-empty q Not a search URL
A url containing tbm Verticals have their own endpoint
pages outside 1 to 10, query longer than 10,000 characters, a device outside the enum Schema limits
Any field not in the schema (for example num or start at the top level) additionalProperties is false

A synchronous call returns HTTP 400 with the validation error shape from the OpenAPI document:

{
  "success": false,
  "error": "Request validation failed",
  "details": [{ "field": "uule", "message": "..." }]
}

For async tasks, validation failures return 422. Retry logic should never retry a 400 or 422 unchanged; see API errors and retries.

Cost in credits

A Google Search async task costs 3 credits, each page after the first adds 2, include.aioverview or include.paaAioverview adds 2 once, and a synchronous call adds 2. An accepted request reserves the maximum cost and is charged for the pages returned; a failed request is not charged.

Request Async task Synchronous call
query + country, 1 page 3 5
pages: 3 7 9
pages: 10 21 23
1 page + include.aioverview 5 7
pages: 3 + include.aioverview 9 11
url with num=30 (3 pages) 7 9

device, hl, location, uule, tbs and safe do not change the price. See /docs/credits and cost planning.

Examples

Python: one keyword across markets and devices

This uses requests and async tasks, which cost less than synchronous calls for volume.

import itertools
import os

import requests

API = "https://api.answerline.dev"
HEADERS = {"Authorization": f"Bearer {os.environ['ANSWERLINE_API_KEY']}"}

markets = [
    {"country": "US", "hl": "en", "location": "New York,New York,United States"},
    {"country": "DE", "hl": "de"},
    {"country": "DE", "hl": "en"},
]
devices = ["desktop", "ios"]

tasks = [
    {
        "taskType": "GOOGLE",
        "payload": {"query": "project management software", **market, "device": device, "pages": 2},
    }
    for market, device in itertools.product(markets, devices)
]

r = requests.post(f"{API}/v1/async/task/batch", json=tasks, headers=HEADERS, timeout=60)
r.raise_for_status()
for task, item in zip(tasks, r.json()["results"]):
    print(task["payload"]["country"], task["payload"]["hl"], task["payload"]["device"], item["success"])

Six tasks at 5 credits each (3 + 2 for the second page) cost 30 credits. Collect results with GET /v1/async/task/{taskId} or a webhook; see async tasks.

TypeScript: the URL shape with a time filter

const params = new URLSearchParams({ q: "\"acme analytics\"", gl: "gb", hl: "en", num: "20", tbs: "qdr:w" });
const res = await fetch("https://api.answerline.dev/v1/monitor/google", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.ANSWERLINE_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({ url: `https://www.google.co.uk/search?${params}`, device: "android" }),
});
if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
const { result } = await res.json();
for (const o of result.organicResults ?? []) console.log(o.page, o.position, o.date, o.link);

This is two pages as a synchronous call: 3 + 2 + 2 = 7 credits.

Validate before sending

Catching shape errors client-side saves a round trip:

def check(body: dict) -> None:
    if "url" in body:
        clash = {"query", "location", "uule", "pages"} & body.keys()
        if clash:
            raise ValueError(f"url cannot be combined with {sorted(clash)}")
    elif "query" not in body or not ({"country", "gl"} & body.keys()):
        raise ValueError("send query with country or gl, or send url")
    if {"location", "uule"} <= body.keys():
        raise ValueError("location and uule are mutually exclusive")
    if "country" in body and "gl" in body and body["country"].upper() != body["gl"].upper():
        raise ValueError("country and gl differ")
    if not 1 <= body.get("pages", 1) <= 10:
        raise ValueError("pages must be 1 to 10")

Pitfalls

Related: Google Custom Search JSON API alternatives, Bing Search API alternatives and what is a SERP.

Full request and response fields are on the Google Search engine page.

Questions

What is the difference between gl and hl in Google search?

gl sets the country the results are for, and hl sets the interface language. In this API, country or gl sets the result geography with an ISO 3166-1 alpha-2 code, and hl overrides the language that would otherwise be derived from the country, so the two can differ.

Does Google's num=100 parameter still work?

Search Engine Roundtable reported in September 2025 that num=100 stopped working. This API reads num in a search URL as result depth, rounded up to whole pages of ten and capped at ten pages, and returns those pages; in the standard request shape you set pages from 1 to 10.

How do I target a city instead of a country?

Send location with a Google canonical name such as New York,New York,United States, or uule with a pre-encoded UULE string, together with country. location and uule are mutually exclusive, and neither can be sent with url; put uule inside the URL instead.

Which parameter combinations return a 400 error?

query together with url; url together with location, uule or pages; location together with uule; country and gl with different values; an unsupported country; a url that is not a Google web search URL with a non-empty q, or that carries tbm; and any field not in the schema.

How many credits does a Google Search request cost?

3 credits as an async task, plus 2 for each page after the first and 2 once for include.aioverview or include.paaAioverview. Synchronous calls add 2. A three-page async task with the AI Overview costs 9 credits.

Try it on your own prompts

500 free credits a month, no card. One POST returns the answer, sources and citations as JSON.

Keep reading