Google API
The TrueScrape Google API exposes 8 public endpoints covering Ad details and Ads run by an advertiser or domain. Every call is a GET against public, logged-out pages and returns the same unified schema as every other platform here. Calls cost 1–5 credits each. A cache hit is free, and a failed or empty response is never charged.
Endpoints
| Endpoint | Returns | Credits | Cacheable | Batchable |
|---|---|---|---|---|
| /v1/google/ad-library/ad | Ad details | 1 | yes | yes |
| /v1/google/ad-library/advertiser-ads | Ads run by an advertiser or domain | 2 | yes | yes |
| /v1/google/ad-library/advertisers | Find advertisers in the Ads Transparency Centre | 1 | yes | yes |
| /v1/google/jobs | Google Jobs results | 5 | yes | yes |
| /v1/google/maps-search | Google Maps place search | 5 | yes | yes |
| /v1/google/news | Google News results | 5 | yes | yes |
| /v1/google/search | Web search results | 1 | yes | yes |
| /v1/google/shopping | Google Shopping results | 5 | yes | yes |
Reference
/v1/google/ad-library/ad1 creditcacheablebatchableAd details
One creative from the Ads Transparency Centre, with every rendering variant and the per-country dates it ran. For a text ad, headline, body and linkUrl come from its rendered preview, and linkUrl is the address the ad displays.
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | yes | Creative URL, e.g. https://adstransparency.google.com/advertiser/AR.../creative/CR...?region=US |
| region | string | no | Overrides the region in the URL |
Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).
Returns one Ad.
Fields
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | |
| advertiserId | string | null | always | |
| advertiserName | string | null | always | |
| url | string | null | always | Link to the ad's page in the platform's ad library. |
| headline | string | null | always | |
| body | string | null | always | |
| ctaText | string | null | always | Text of the call-to-action button, such as "Shop now". |
| linkUrl | string | null | always | Where the ad links to. Some ad libraries expose only the destination's domain. |
| creativeType | string | null | always | Format of the ad creative, such as `video` or `image`, as the ad library labels it. |
| imageUrls | string[] | always | |
| videoUrls | string[] | always | |
| platforms | string[] | always | Platforms the ad was shown on, in lowercase, such as `facebook` or `instagram`. |
| countries | string[] | always | Countries the ad ran in or targeted, usually as two-letter country codes. |
| languages | string[] | always | |
| startedAt | string | null | always | |
| endedAt | string | null | always | When the ad stopped running. Null while it is still running, or when the ad library reports no end date. |
| isActive | boolean | null | always | |
| impressionsLower | number | null | always | Lower bound of the impressions range the ad library reports. Libraries publish a range, not an exact figure. |
| impressionsUpper | number | null | always | Upper bound of the impressions range the ad library reports. |
| spendLower | number | null | always | Lower bound of the reported spend range, in `currency`. |
| spendUpper | number | null | always | Upper bound of the reported spend range, in `currency`. |
| currency | string | null | always | Currency of the spend range, as a code such as `USD`. |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/google/ad-library/ad?url=8XkPqR2nLvE&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
url: '8XkPqR2nLvE',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/google/ad-library/ad?${query}`, {
headers: { 'x-api-key': KEY },
});
const body = await response.json();
if (!body.success) throw new Error(body.error.code);
// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);Python
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/google/ad-library/ad",
params={
"url": "8XkPqR2nLvE",
"cache_max_age": "7d",
},
headers={"x-api-key": os.environ["KEY"]},
timeout=30,
)
body = r.json()
if not body["success"]:
raise RuntimeError(body["error"]["code"])
print(body["data"], body["meta"]["creditsCharged"])Response codes
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/google/ad-library/advertiser-ads2 creditscacheablebatchableAds run by an advertiser or domain
Creatives in the Ads Transparency Centre for one advertiser id or one verified domain, with first-shown and last-shown dates. Pass the cursor from the previous response to page. **Required:** Pass either domain or advertiser_id.
| Parameter | Type | Required | Description |
|---|---|---|---|
| domain | string | no | Verified advertiser domain, e.g. "nike.com" |
| advertiser_id | string | no | Advertiser id from /ad-library/advertisers, e.g. "AR167..." |
| region | string | no | Two-letter country code (US, GB, DE, IN, ...) or a Google geo criteria iddefaults to US |
| cursor | string | no | Continuation token from the previous response |
Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).
Returns an object with items, totalLower, totalUpper.
Fields
| Field | Type | Present | Description |
|---|---|---|---|
| items | Ad[] | always | |
| totalLower | number | null | always | Lower bound of the archive estimate of how many ads match, across every page. |
| totalUpper | number | null | always | Upper bound of that estimate. |
curl "$API/v1/google/ad-library/advertiser-ads?cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/google/ad-library/advertiser-ads?${query}`, {
headers: { 'x-api-key': KEY },
});
const body = await response.json();
if (!body.success) throw new Error(body.error.code);
// 2 credits, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);Python
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/google/ad-library/advertiser-ads",
params={
"cache_max_age": "7d",
},
headers={"x-api-key": os.environ["KEY"]},
timeout=30,
)
body = r.json()
if not body["success"]:
raise RuntimeError(body["error"]["code"])
print(body["data"], body["meta"]["creditsCharged"])Response codes
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/google/ad-library/advertisers1 creditcacheablebatchableFind advertisers in the Ads Transparency Centre
Advertisers matching a name, with the advertiser id that /v1/google/ad-library/advertiser-ads needs, plus the verified domains Google suggests for the same term in domains. Without region every region is searched. postCount and adCountUpper are the lower and upper bounds of the ad-count range the archive publishes, counted within region when one is given.
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | string | yes | Advertiser or brand name, e.g. "nike" |
| region | string | no | Two-letter country code (US, GB, DE, IN, ...) or a Google geo criteria id. Omit to search every region. |
Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).
Returns an object with items, domains.
Fields
| Field | Type | Present | Description |
|---|---|---|---|
| items | object[] | always | |
| items[].platform | one of 32 strings | always | |
| items[].id | string | always | The platform's own id for the account, such as a channel id or a numeric user id, always as a string. |
| items[].handle | string | null | always | The account handle without the leading @. Null when the platform has no handles. |
| items[].displayName | string | null | always | |
| items[].bio | string | null | always | |
| items[].avatarUrl | string | null | always | |
| items[].bannerUrl | string | null | always | |
| items[].url | string | null | always | |
| items[].verified | boolean | null | always | Whether the platform shows a verification badge on the account. Null where the platform has no public badge or does not expose it. |
| items[].followerCount | number | null | always | Followers, subscribers, or the platform's nearest equivalent. Null when the account hides the count or the platform does not expose it. |
| items[].followingCount | number | null | always | |
| items[].postCount | number | null | always | Posts, videos, tracks, repositories, or the platform's nearest equivalent that the account has published. |
| items[].viewCount | number | null | always | Lifetime views across the account, where the platform exposes a total. |
| items[].likeCount | number | null | may be absent | Total likes received across all of the creator's posts. Distinct from `viewCount`. Absent when the platform does not expose it. |
| items[].isPrivate | boolean | null | always | |
| items[].isBusiness | boolean | null | always | Whether the platform classifies the account as a business or organisation rather than a person or creator. Null where the platform draws no such line or does not expose it. On Facebook every Page counts, including Pages for public figures. |
| items[].category | string | null | always | A label the platform attaches to the account, such as a business category, a genre or an account type. What it holds varies by platform. |
| items[].location | string | null | always | Location as the platform shows it: a city, a country, a region code or an address, depending on the platform. |
| items[].externalLinks | string[] | always | Links the account lists on its profile, such as a website or other social accounts. |
| items[].createdAt | string | null | always | When the account was created. Usually an ISO 8601 timestamp; some platforms expose only the date as shown on the profile. |
| items[].fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
| items[].adCountUpper | number | null | always | Upper bound of the ad-count range the archive publishes; `postCount` is the lower bound. |
| domains | string[] | always |
curl "$API/v1/google/ad-library/advertisers?query=ai%20agents&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
query: 'ai agents',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/google/ad-library/advertisers?${query}`, {
headers: { 'x-api-key': KEY },
});
const body = await response.json();
if (!body.success) throw new Error(body.error.code);
// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);Python
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/google/ad-library/advertisers",
params={
"query": "ai agents",
"cache_max_age": "7d",
},
headers={"x-api-key": os.environ["KEY"]},
timeout=30,
)
body = r.json()
if not body["success"]:
raise RuntimeError(body["error"]["code"])
print(body["data"], body["meta"]["creditsCharged"])Response codes
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/google/jobs5 creditscacheablebatchableGoogle Jobs results
Job postings for a query: title, company, location and the board it was syndicated from. Shares the /search anti-bot gate google.search already documents; a blocked attempt returns upstream_blocked and is not charged.
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | string | yes | Search query |
| tld | string | no | Google marketplace TLD. One of: com, co.uk, ca, de, es, fr, it, co.jp, in, cn, com.sg, com.mx, ae, com.br, nl, com.au, com.tr, sa, se, pl. Defaults to "com".defaults to com |
| country_code | string | no | Two-letter country code. Sets gl when gl is not given. |
| hl | string | no | Host language for the results page, e.g. "en", "de". Defaults to "en".defaults to en |
| gl | string | no | Two-letter country code Google should bias results toward. |
| uule | string | no | Encoded Google location string for precise geo-targeting. |
| start | number | no | 0-based result offset. |
Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).
Returns a list of JobPosting in data.items.
Fields
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | null | always | Identifier for the posting. Where the source shows none, this is the posting URL. |
| title | string | null | always | |
| company | string | null | always | |
| location | string | null | always | |
| via | string | null | always | The job board the posting was listed through, as in "via LinkedIn". |
| description | string | null | always | Snippet of the job description shown with the result. |
| url | string | null | always | |
| tags | string[] | always | |
| postedAt | string | null | always | |
| fetchedAt | string | always | When this record was retrieved, as an ISO 8601 timestamp. |
curl "$API/v1/google/jobs?query=ai%20agents&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
query: 'ai agents',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/google/jobs?${query}`, {
headers: { 'x-api-key': KEY },
});
const body = await response.json();
if (!body.success) throw new Error(body.error.code);
// 5 credits, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);Python
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/google/jobs",
params={
"query": "ai agents",
"cache_max_age": "7d",
},
headers={"x-api-key": os.environ["KEY"]},
timeout=30,
)
body = r.json()
if not body["success"]:
raise RuntimeError(body["error"]["code"])
print(body["data"], body["meta"]["creditsCharged"])Response codes
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/google/maps-search5 creditscacheablebatchableGoogle Maps place search
Business listings near a coordinate: name, address, phone, rating and hours. Google Maps requires JavaScript to render its result list; an unrendered response returns upstream_blocked and is not charged, rather than a silent empty success.
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | string | yes | Search query |
| tld | string | no | Google marketplace TLD. One of: com, co.uk, ca, de, es, fr, it, co.jp, in, cn, com.sg, com.mx, ae, com.br, nl, com.au, com.tr, sa, se, pl. Defaults to "com".defaults to com |
| country_code | string | no | Two-letter country code. Sets gl when gl is not given. |
| hl | string | no | Host language for the results page, e.g. "en", "de". Defaults to "en".defaults to en |
| gl | string | no | Two-letter country code Google should bias results toward. |
| uule | string | no | Encoded Google location string for precise geo-targeting. |
| start | number | no | 0-based result offset. |
| latitude | number | yes | Latitude of the search centre |
| longitude | number | yes | Longitude of the search centre |
Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).
Returns a list of Place in data.items.
Fields
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | null | always | |
| name | string | null | always | |
| address | Address | always | |
| latitude | number | null | always | |
| longitude | number | null | always | |
| phone | string | null | always | |
| website | string | null | always | The business's own website. |
| url | string | null | always | Link to the place's listing on the map service. |
| rating | number | null | always | Average star rating, out of 5. |
| reviewCount | number | null | always | |
| priceLevel | string | null | always | Price band as the listing shows it, such as `$` or `$$`. The scale varies by locale. |
| categories | string[] | always | |
| hours | Record<string, string[]> | always | Opening hours keyed by lowercase weekday, such as `monday`. Each value is the hours text as the listing published it. |
| imageUrls | string[] | always | |
| fetchedAt | string | always | When this record was retrieved, as an ISO 8601 timestamp. |
curl "$API/v1/google/maps-search?query=ai%20agents&latitude=%3Clatitude%3E&longitude=%3Clongitude%3E&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
query: 'ai agents',
latitude: '<latitude>',
longitude: '<longitude>',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/google/maps-search?${query}`, {
headers: { 'x-api-key': KEY },
});
const body = await response.json();
if (!body.success) throw new Error(body.error.code);
// 5 credits, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);Python
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/google/maps-search",
params={
"query": "ai agents",
"latitude": "<latitude>",
"longitude": "<longitude>",
"cache_max_age": "7d",
},
headers={"x-api-key": os.environ["KEY"]},
timeout=30,
)
body = r.json()
if not body["success"]:
raise RuntimeError(body["error"]["code"])
print(body["data"], body["meta"]["creditsCharged"])Response codes
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/google/news5 creditscacheablebatchableGoogle News results
News articles for a query: title, source, and published time. Shares the /search anti-bot gate google.search already documents; a blocked attempt returns upstream_blocked and is not charged.
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | string | yes | Search query |
| tld | string | no | Google marketplace TLD. One of: com, co.uk, ca, de, es, fr, it, co.jp, in, cn, com.sg, com.mx, ae, com.br, nl, com.au, com.tr, sa, se, pl. Defaults to "com".defaults to com |
| country_code | string | no | Two-letter country code. Sets gl when gl is not given. |
| hl | string | no | Host language for the results page, e.g. "en", "de". Defaults to "en".defaults to en |
| gl | string | no | Two-letter country code Google should bias results toward. |
| uule | string | no | Encoded Google location string for precise geo-targeting. |
| start | number | no | 0-based result offset. |
| tbs | h | d | w | m | y | no | Time filter: hour/day/week/month/year, as Google's own qdr code. |
Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).
Returns a list of NewsArticle in data.items.
Fields
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| position | number | null | always | Rank of the article in the results, starting at 1. |
| title | string | null | always | |
| source | string | null | always | Name of the outlet that published the article. |
| description | string | null | always | Snippet of the article shown with the result. |
| link | string | null | always | |
| thumbnailUrl | string | null | always | |
| publishedAt | string | null | always | When the article was published, as the result displays it. Often relative, such as "2 hours ago", and not converted to a date. |
| fetchedAt | string | always | When this record was retrieved, as an ISO 8601 timestamp. |
curl "$API/v1/google/news?query=ai%20agents&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
query: 'ai agents',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/google/news?${query}`, {
headers: { 'x-api-key': KEY },
});
const body = await response.json();
if (!body.success) throw new Error(body.error.code);
// 5 credits, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);Python
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/google/news",
params={
"query": "ai agents",
"cache_max_age": "7d",
},
headers={"x-api-key": os.environ["KEY"]},
timeout=30,
)
body = r.json()
if not body["success"]:
raise RuntimeError(body["error"]["code"])
print(body["data"], body["meta"]["creditsCharged"])Response codes
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/google/search1 creditcacheablebatchableWeb search results
Organic Google results for a query. Google blocks automated queries harder than any other source here, so this endpoint fails more often than the rest; a blocked attempt returns upstream_blocked and is not charged.
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | string | yes | — |
| region | string | no | Two-letter country code (US, GB, DE, IN, ...) or a Google geo criteria iddefaults to US |
| date_posted | hour | day | week | month | year | no | — |
| page | string | no | 1-based page number |
Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).
Returns a list of Post in data.items.
Fields
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | |
| type | video | short | image | carousel | text | live | story | reel | audio | album | episode | unknown | always | What kind of post this is. `short` and `reel` are short-form video formats, `live` is a live stream or a recording of one, `carousel` holds several images or videos, `audio` is a music track, `album` is an album, `episode` is a podcast episode, and `unknown` covers anything else. |
| url | string | null | always | |
| title | string | null | always | |
| text | string | null | always | The post's text: a caption, a description or the message body. |
| authorId | string | null | always | |
| authorHandle | string | null | always | |
| authorName | string | null | always | |
| thumbnailUrl | string | null | always | |
| mediaUrls | string[] | always | |
| durationSeconds | number | null | always | |
| viewCount | number | null | always | Views. Null means the platform did not expose a count, which is not the same as zero. |
| likeCount | number | null | always | Likes, or the platform's nearest equivalent. Null means not exposed, not zero. |
| commentCount | number | null | always | Comments. Null means not exposed, not zero. |
| shareCount | number | null | always | Shares, reposts, or the platform's nearest equivalent. Null means not exposed, not zero. |
| hashtags | string[] | always | Hashtags or the platform's own topic tags, without the leading #. |
| mentions | string[] | always | Handles mentioned in the post text, without the leading @. |
| taggedUsers | string[] | may be absent | Usernames tagged in the media itself, as distinct from `mentions`, which come from the caption text. Absent when the platform does not report tags; an empty array means it reports none. |
| isSponsored | boolean | null | always | Whether the platform labels the post as an ad, promoted content or a paid partnership. |
| publishedAt | string | null | always | When the post was published. Usually an ISO 8601 timestamp; some platforms expose only a date or relative text such as "3 days ago". |
| fetchedAt | string | always | When this record was fetched from the platform, as an ISO 8601 timestamp. A cached response keeps the time of the original fetch. |
curl "$API/v1/google/search?query=ai%20agents&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
query: 'ai agents',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/google/search?${query}`, {
headers: { 'x-api-key': KEY },
});
const body = await response.json();
if (!body.success) throw new Error(body.error.code);
// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);Python
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/google/search",
params={
"query": "ai agents",
"cache_max_age": "7d",
},
headers={"x-api-key": os.environ["KEY"]},
timeout=30,
)
body = r.json()
if not body["success"]:
raise RuntimeError(body["error"]["code"])
print(body["data"], body["meta"]["creditsCharged"])Response codes
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/google/shopping5 creditscacheablebatchableGoogle Shopping results
Shopping tiles for a query: title, price, currency and merchant. Shares the /search anti-bot gate google.search already documents; a blocked attempt returns upstream_blocked and is not charged.
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | string | yes | Search query |
| tld | string | no | Google marketplace TLD. One of: com, co.uk, ca, de, es, fr, it, co.jp, in, cn, com.sg, com.mx, ae, com.br, nl, com.au, com.tr, sa, se, pl. Defaults to "com".defaults to com |
| country_code | string | no | Two-letter country code. Sets gl when gl is not given. |
| hl | string | no | Host language for the results page, e.g. "en", "de". Defaults to "en".defaults to en |
| gl | string | no | Two-letter country code Google should bias results toward. |
| uule | string | no | Encoded Google location string for precise geo-targeting. |
| start | number | no | 0-based result offset. |
| tbs | h | d | w | m | y | no | Time filter: hour/day/week/month/year, as Google's own qdr code. |
Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).
Returns a list of SearchResultItem in data.items.
Fields
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| position | number | null | always | Rank of the result on the page it was read from, starting at 1, in the order the source served it. |
| id | string | null | always | The listing id on its platform, such as an Amazon ASIN. Where the source shows no id, this is the result URL, or the title when there is no URL. |
| title | string | null | always | |
| url | string | null | always | |
| thumbnailUrl | string | null | always | |
| price | number | null | always | Price shown on the result, in `currency`. Where a price range is shown, the lowest price. |
| currency | string | null | always | ISO 4217 currency code for the amounts in this record, such as USD or EUR. |
| listPrice | number | null | always | The struck-through reference price shown on the result, when there is one. |
| rating | number | null | always | Average customer rating, out of 5. |
| reviewCount | number | null | always | |
| sellerName | string | null | always | |
| availability | in_stock | out_of_stock | preorder | discontinued | unknown | null | always | Stock status. `unknown` means the listing showed a status that could not be read as one of the other values. |
| badges | string[] | always | Labels shown on the result, such as Best Seller or Amazon's Choice. |
| isSponsored | boolean | null | always | True for a paid placement. False only where the source marks a result as not sponsored; a result with no sponsored label is null. |
| fetchedAt | string | always | When this record was retrieved, as an ISO 8601 timestamp. |
curl "$API/v1/google/shopping?query=ai%20agents&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
query: 'ai agents',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/google/shopping?${query}`, {
headers: { 'x-api-key': KEY },
});
const body = await response.json();
if (!body.success) throw new Error(body.error.code);
// 5 credits, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);Python
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/google/shopping",
params={
"query": "ai agents",
"cache_max_age": "7d",
},
headers={"x-api-key": os.environ["KEY"]},
timeout=30,
)
body = r.json()
if not body["success"]:
raise RuntimeError(body["error"]["code"])
print(body["data"], body["meta"]["creditsCharged"])Response codes
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
Questions
- How much does the Google API cost?
- Calls cost 1–5 credits each. Every endpoint is cacheable, and a cache hit costs nothing. A failed request and an empty result are both free, on every endpoint.
- Does the Google API need a login or cookies?
- No. Every endpoint reads public, logged-out pages only — no account, no cookies, no session. An API key identifies your own TrueScrape account and nothing else.
- Can I fetch many Google targets in one request?
- Yes. 8 of 8 are batchable: one POST to /v1/jobs/batch takes many targets and returns a job id to poll.
- Can I watch Google endpoints for changes?
- Yes, 4 of 8. A subscription polls on your schedule and fires your webhook only when the content changed; the rest carry x-subscribable: false in the spec.