Google Images Scraper API: Read the Images Vertical as JSON
Advanced Data Extraction Specialist
Key Takeaways:
- One POST, no browser. Google Images data comes from a single
POSTto thescraper.google.searchactor withtbm: "isch". The Scraper API renders the page and parses it server-side; you read JSON back. - The image vertical is one input field.
tbm: "isch"flips the Google search actor to the Images vertical;qcarries your query. Everything else is optional. - One auth header everywhere. Every call carries
x-api-token: <your key>. One account key covers the actor and every otherscraper.*actor. - Parsed JSON, flattened at the top level. The actor returns
metadata,search_information, andsuggested_searchesdirectly — noresultwrapper to unwrap. Each refinement chip insuggested_searchescarries an inlinedata:image/jpeg;base64thumbnail. - The full image grid lives at
metadata.rawUrl. The parsed object surfaces the refinement chips and search metadata;metadata.rawUrlpoints at the stored, fully rendered Google Images page when you need every image URL the parsed object does not flatten. - Free to start. New Scrapeless accounts include free Scraper API credits — sign up at app.scrapeless.com.
Introduction: read the Images vertical as JSON
Google Images sits on top of one of the largest visual indexes on the open web, and a lot of work depends on what it surfaces: visual product research, brand and logo monitoring, building image datasets for model training, tracking how a query renders across regions, and pulling design references at scale. The query is the input; a grid of images and a row of refinement chips is the output.
Getting that output programmatically is the hard part. The Images page is JavaScript-rendered, the thumbnails are inlined as base64 inside the script payload, the refinement chips and image URLs are buried in the page's hydration data, and an anonymous request gets a challenge instead of a grid. A hand-rolled scraper has to render the page, get past the anti-bot layer, and reverse-engineer the markup — three jobs, all of which shift when Google ships a redesign.
This guide walks through the scraper.google.search actor on the Scrapeless Scraper API, run with tbm: "isch". One HTTP request returns a parsed object plus a stored copy of the rendered image page. No browser to drive, no parser to maintain. The worked example below is the real q: "golden retriever" capture; a companion Scraper API guide covers the AI-answer family with the same request shape.
Why the Scraper API for Google Images
- No browser, no parser to maintain. The actor renders and parses the Images page on the server; you receive structured fields, not a DOM to walk or a base64 blob to decode by hand.
- One input flips the vertical. The same Google search actor serves web results and images — set
tbm: "isch"and the response comes back as the Images vertical. - Residential egress and rendering are built in. Geo-routing and JavaScript rendering run inside the actor; you send
{ actor, input }and read the result. - One shape to read. The parsed Images object is flattened at the top level, so a client wrapper written once handles the response without unwrapping nested envelopes.
Get your API key on the free plan at app.scrapeless.com. The Google search actor is part of Deep SerpApi, which sits in the pricing catalogue.
Prerequisites
- A Scrapeless account and API key — sign up at app.scrapeless.com.
curlfor the quick test, or Python 3.10+ for the client below.- Basic familiarity with HTTP and JSON.
Store your key in the environment so it never lands in code:
bash
export SCRAPELESS_API_KEY=your_api_token_here
The request
Google Images uses the site/SERP endpoint. You name the actor, hand it an input, and send your key in the header.
- Endpoint:
POST https://api.scrapeless.com/api/v1/scraper/request - Actor:
scraper.google.search - Auth header:
x-api-token: $SCRAPELESS_API_KEY
The body is { "actor": "<name>", "input": { … } }. For the Images vertical the input is two fields:
json
{
"actor": "scraper.google.search",
"input": { "q": "golden retriever", "tbm": "isch" }
}
| input field | required | description |
|---|---|---|
q |
yes | the image search query string |
tbm |
yes | search vertical — "isch" selects Google Images |
hl |
no | UI language, e.g. "en" |
gl |
no | country / locale, e.g. "us" |
google_domain |
no | Google domain to hit, e.g. ".google.com" |
Example — curl and Python
The quickest check is a single curl call:
bash
curl -sS -X POST https://api.scrapeless.com/api/v1/scraper/request \
-H "Content-Type: application/json" \
-H "x-api-token: ${SCRAPELESS_API_KEY}" \
-d '{
"actor": "scraper.google.search",
"input": { "q": "golden retriever", "tbm": "isch" }
}'
The same request in Python, with the response parsed straight into a dict:
python
import os
import json
import requests
ENDPOINT = "https://api.scrapeless.com/api/v1/scraper/request"
def scrape_google_images(query: str) -> dict:
resp = requests.post(
ENDPOINT,
headers={
"Content-Type": "application/json",
"x-api-token": os.environ["SCRAPELESS_API_KEY"],
},
json={"actor": "scraper.google.search", "input": {"q": query, "tbm": "isch"}},
timeout=120,
)
resp.raise_for_status()
return resp.json()
if __name__ == "__main__":
data = scrape_google_images("golden retriever")
# google.search flattens the parsed result at the top level,
# so data.get("result", data) falls back to the whole response.
print(json.dumps(data.get("result", data), indent=2, ensure_ascii=False))
Because the Google search actor flattens its parsed output at the top level, there is no result key to reach into — data.get("result", data) simply returns the whole response, and you read search_information and suggested_searches directly off it.
Get your API key on the free plan: app.scrapeless.com
What You Get Back
For the Images vertical the actor surfaces a Scrapeless metadata envelope, the search_information Google echoes, and the row of image-refinement chips (suggested_searches) that Google renders above the grid. Each chip carries its own inline thumbnail. This is the real capture for q: "golden retriever", tbm: "isch":
json
// Real capture for q:"golden retriever", tbm:"isch".
// base64 thumbnails trimmed; suggested_searches abridged to 2 of 5 chips — illustrative sample.
{
"metadata": {
"engine": "google.search",
"rawUrl": "https://api.scrapeless.com/storage/scrapeless.scraper.google.search/…_1781025000.html"
},
"pagination": {},
"search_information": {
"organic_results_state": "Results for exact spelling",
"query_displayed": "golden retriever",
"total_results": 0,
"time_taken_displayed": ""
},
"suggested_searches": [
{
"name": "Puppy",
"link": "https://www.google.com/search?sca_esv=…&gl=us&q=golden+retriever+puppy&uds=…&udm=2&sa=X&…",
"uds": "",
"q": "Puppy golden retriever",
"thumbnail": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/…"
},
{
"name": "Cute",
"link": "https://www.google.com/search?sca_esv=…&gl=us&q=cute+golden+retriever&uds=…&udm=2&sa=X&…",
"uds": "",
"q": "Cute golden retriever",
"thumbnail": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/…"
}
]
}
Field by field:
| field | type | what it holds |
|---|---|---|
metadata.engine |
string | the actor engine that served the request — "google.search" |
metadata.rawUrl |
string (URL) | stored copy of the fully rendered Google Images page; fetch it for the complete image grid |
pagination |
object | pagination cursors; an empty object on this capture |
search_information.query_displayed |
string | the query Google echoed back ("golden retriever") |
search_information.organic_results_state |
string | the spelling / results state ("Results for exact spelling") |
search_information.total_results |
number | the result count Google reported — 0 for the image vertical here |
search_information.time_taken_displayed |
string | Google's timing string; empty on this capture |
suggested_searches[] |
array | the image-refinement chips rendered above the grid |
suggested_searches[].name |
string | the chip label ("Puppy", "Cute", "Labrador", …) |
suggested_searches[].q |
string | the refined query the chip runs ("Puppy golden retriever") |
suggested_searches[].link |
string (URL) | the Google Images search URL for that refinement (udm=2 is Google's image-vertical parameter) |
suggested_searches[].uds |
string | Google's uds chip token; empty on this capture |
suggested_searches[].thumbnail |
string | an inline data:image/jpeg;base64 preview for the chip |
A few honest observations on the shape:
- The parsed object surfaces the refinement chips, not a flat
images_resultsarray. For theischvertical the actor returnssuggested_searchesplus the rendered page atmetadata.rawUrl. When you need every image URL on the grid, fetchmetadata.rawUrl— that stored page holds the full set the parsed object does not flatten. - Thumbnails are inline base64. Each chip's
thumbnailis a completedata:image/jpeg;base64value, usable without a second request; the fixture trims them for readability. search_informationmirrors what Google shows.total_resultsandtime_taken_displayedcan come back0and empty on the image vertical, where Google does not render the "About N results" line it shows for web search.- Treat per-chip fields as nullable.
udsis present on every chip but empty in this capture, and the chip count varies by query — read what is there rather than assuming a fixed length.
Conclusion
Reading Google Images comes down to one decision and one request: point the scraper.google.search actor at the Images vertical with tbm: "isch", send { actor, input } with your x-api-token, and read the parsed fields back. The response flattens at the top level — metadata, search_information, and the suggested_searches refinement chips with their inline thumbnails — and metadata.rawUrl holds the fully rendered page for the complete grid. Write the client wrapper once, point it at the query you need, and the same shape covers the AI-answer actors when the pipeline grows.
Ready to Build Your AI-Powered Image Data Pipeline?
Join our community to claim a free plan and connect with developers building Google Images pipelines: Discord · Telegram.
Sign up at app.scrapeless.com for free Scraper API credits, and point the scraper.google.search actor at the queries, languages, and regions your image pipeline needs.
FAQ
Q: Is scraping Google Images legal?
The actor collects publicly visible data. Rules vary by jurisdiction and by Google's terms of service, so review the relevant ToS and consult counsel for your use case before running at scale. Never collect personal data protected under GDPR or CCPA, and respect the rights attached to individual images.
Q: How do I authenticate?
Every request carries the header x-api-token: <your key>. One account key works across scraper.google.search and every other actor. Create a key on the free plan at app.scrapeless.com.
Q: How do I switch from web results to images?
Set tbm: "isch" in the input. The same scraper.google.search actor serves the web SERP by default; tbm: "isch" selects the Images vertical and changes the parsed shape to the image-refinement chips plus the rendered image page.
Q: Where are the actual image URLs?
The parsed object surfaces the refinement chips (suggested_searches) and the search metadata. The full grid of image URLs lives in the page stored at metadata.rawUrl — fetch that URL when you need every image on the result page, not just the refinement row.
Q: Can I narrow results by language or country?
Yes. The optional hl (UI language), gl (country / locale), and google_domain inputs scope the request — for example { "q": "golden retriever", "tbm": "isch", "hl": "en", "gl": "us" }.
Q: Do I need a proxy?
No. Residential egress and geo-routing are built into the actor — you send the input, and the actor handles the network and rendering layer.
Q: Can I run this without an SDK or AI agent?
Yes. It is plain HTTP — curl, Python requests, Node fetch, or any language with an HTTP client works directly against POST /api/v1/scraper/request. No SDK is required.
At Scrapeless, we only access publicly available data while strictly complying with applicable laws, regulations, and website privacy policies. The content in this blog is for demonstration purposes only and does not involve any illegal or infringing activities. We make no guarantees and disclaim all liability for the use of information from this blog or third-party links. Before engaging in any scraping activities, consult your legal advisor and review the target website's terms of service or obtain the necessary permissions.



