How to Scrape Google Images as JSON With Full-Resolution URLs
Google Images looks like a simple grid of pictures, but it is one of the harder pages on the web to scrape. What you see is not what is in the HTML. The thumbnails are lazy-loaded, the full-resolution originals are hidden behind a click and a second request, and the URLs that do sit in the markup are often base64 blobs or short-lived redirects rather than the real image on the publisher’s site. Write a naive scraper and you end up with a folder of 200-pixel previews and no idea where any of them came from.
The new Google Images plugin removes that whole problem. You send a keyword, and you get back a JSON array where every result already carries the full-resolution original image URL, the page it appears on, and the source domain. This post explains why Google Images is tricky, what the plugin returns, and how to build a real image dataset with it.
Why Google Images Is Hard to Scrape
Before the plugin, the standard approaches all had a catch:
- The visible thumbnails are downscaled. The
srcyou can read straight out of the grid points at a Google-hosted thumbnail, usually a few hundred pixels wide. That is fine for a preview, useless if you need the real asset. - Original URLs are deferred. The full-resolution image lives on the publisher’s own server, and Google only reveals that URL after interaction. It is tucked inside a JavaScript payload, not the initial HTML, so a plain HTTP fetch never sees it.
- The markup is deliberately noisy. Class names are obfuscated and change often, inline data is encoded, and much of the page is built client-side. Selectors that work today break next week.
- It is a bot-sensitive Google surface. Hammer the results page from a single IP with no browser fingerprint and you get a challenge or an empty page instead of results.
You can solve all of that yourself with a headless browser, careful waiting, and payload parsing, but it is a lot of brittle code to maintain for what should be a simple lookup.
What the Google Images Plugin Returns
The plugin takes a search phrase - the same thing you would type into Google Images - and returns the image results as a structured JSON array. The key detail is that imageUrl is the real, full-resolution image on the source website, not a Google thumbnail.
For each result you get fields like:
position- rank in the resultstitle- the image’s alt/title textimageUrl- the full-resolution original image URL on the publisher’s sitesourceUrl- the page the image appears onsourceDomain- the host of that page, such asexample.comsiteName- the human-readable site name where availablethumbnailUrl- the Google-hosted preview, if you want a lightweight versionwidthandheight- the original image dimensions in pixels
Because the original URL and the source page come back together, you always know both what the image is and where it legitimately lives - which matters a lot for licensing and attribution.
The Request
The endpoint is a single POST call. The only required parameter is q, the search phrase. A few optional parameters control location, language, and result count:
q(required) - the search phrase, for examplered pandaproxy_country- the exit-IP country as an ISO-2 code (US,GB,DE)gl- the Google country of search, lowercase ISO-2 (us,de,fr)max_results- how many images to return, from 1 to 100
Here is the simplest possible call with curl:
curl -X POST "https://api.scrapeunblocker.com/images/google-search?q=red%20panda&max_results=20" \
-H "x-scrapeunblocker-key: YOUR_API_KEY"
That returns the top image results for the keyword, each with its full-resolution URL, in one response. You do not manage a browser, wait for lazy loading, or parse any HTML.
The Response
The response is a single JSON object. The top level echoes the query and how many results came back, and the results array holds the images:
{
"q": "red panda",
"proxyCountry": "US",
"resultsCollected": 20,
"results": [
{
"position": 1,
"title": "Red panda resting on a branch",
"imageUrl": "https://example.com/photos/red-panda-full.jpg",
"sourceUrl": "https://example.com/wildlife/red-panda",
"sourceDomain": "example.com",
"siteName": "Example Wildlife",
"thumbnailUrl": "https://encrypted-tbn0.gstatic.com/images?q=...",
"width": 2400,
"height": 1600
}
]
}
Because the shape is stable, you can map it straight into a database, a spreadsheet, or a download queue with no HTML cleanup.
Calling It From Python
You do not need the SDK to use the plugin - any HTTP client works. Here is a small example with requests that runs a search and prints each result:
import requests
API_KEY = "YOUR_API_KEY"
URL = "https://api.scrapeunblocker.com/images/google-search"
params = {
"q": "red panda",
"proxy_country": "US",
"gl": "us",
"max_results": 20,
}
resp = requests.post(URL, params=params, headers={"x-scrapeunblocker-key": API_KEY})
resp.raise_for_status()
data = resp.json()
for img in data["results"]:
print(f"{img['position']:>2}. {img['width']}x{img['height']} "
f"{img['sourceDomain']:<20} {img['imageUrl']}")
If you prefer official tooling, ScrapeUnblocker ships SDKs for Python, Node.js, Ruby, and PHP, and the plugin is available through the dashboard and API reference as well. The Python package installs with pip install scrapeunblocker and reads your key from an environment variable, so you can skip passing the header by hand.
Downloading the Actual Images
The point of getting the full-resolution URL is that you can fetch the real file. Here is a search-then-download loop that saves each original image to disk, named by source domain:
import os
import requests
from urllib.parse import urlparse
API_KEY = "YOUR_API_KEY"
SEARCH_URL = "https://api.scrapeunblocker.com/images/google-search"
os.makedirs("images", exist_ok=True)
params = {"q": "vintage typewriter", "max_results": 30}
data = requests.post(SEARCH_URL, params=params,
headers={"x-scrapeunblocker-key": API_KEY}).json()
for img in data["results"]:
url = img["imageUrl"]
ext = os.path.splitext(urlparse(url).path)[1] or ".jpg"
name = f"images/{img['position']:02d}_{img['sourceDomain']}{ext}"
try:
r = requests.get(url, timeout=20)
r.raise_for_status()
with open(name, "wb") as f:
f.write(r.content)
print("saved", name)
except requests.RequestException as e:
print("skip", url, e)
Because imageUrl points at the origin server rather than a Google thumbnail, some hosts may rate-limit or hotlink-protect their images. Wrap the download in a try/except, add a short delay between requests, and skip the ones that fail rather than letting one bad host stop the run.
What You Can Build With It
Image search results as clean JSON open up a few practical use cases:
- Training and reference datasets. Collect labelled images for a category, keeping the
title,sourceUrl, andsourceDomainalongside each file so you can trace provenance and filter by license later. - Brand and logo monitoring. Search for your brand or product name and see which sites are using your imagery, and at what resolution.
- Content and SEO research. Check which images rank for a keyword, how large they are, and which domains dominate the results for a topic.
- Product and catalog enrichment. Pull candidate images for products by name, then pick the highest-resolution result for each.
Because each result carries width and height, you can filter for images above a minimum size in one line before you download anything.
Practical Tips
A few things worth keeping in mind:
- Be specific with keywords. Broad terms return generic stock imagery; a precise phrase returns a tighter, more relevant set. Treat
qexactly as you would a real Google Images search. - Set location when it matters. Image results can vary by region. Use
proxy_countryandgltogether when you need reproducible, location-accurate results. - Filter by dimensions early. Use
widthandheightto drop tiny images before spending bandwidth downloading them. - Respect licensing. A public image URL is not the same as a license to use it. Keep the
sourceUrlandsiteNamewith every image and check usage rights before you publish or redistribute anything. - Handle download failures gracefully. The originals live on third-party servers, so expect some 403s and timeouts and skip past them.
FAQ
Do I get the real image or just a thumbnail?
You get the real one. imageUrl is the full-resolution original hosted on the source site. A thumbnailUrl is also included if you want a lightweight preview.
How many images can one call return?
Up to 100, controlled by max_results. Set it to the number you actually need to keep responses small and fast.
Can I target a specific country or language?
Yes. Use proxy_country for the exit IP and gl for the Google country of search. Set both when you care about which region’s results you get.
Is scraping Google Images legal? Reading public search results is generally fine, but the images themselves are copyrighted works owned by their publishers. Getting a URL is not a license. Always check and respect the usage rights of each image before reusing it.
What if I need images from a specific site instead?
Add a site: style term to your query, or fetch that site’s pages directly with the standard scraping endpoint and pull the images you need from the markup.
Wrapping Up
Google Images turns a simple-looking grid into a scraping headache: downscaled thumbnails, deferred original URLs, obfuscated markup, and a bot-sensitive surface. The Google Images plugin collapses all of that into one call that returns full-resolution image URLs, source pages, and dimensions as clean JSON, so you can spend your time building the dataset instead of reverse-engineering the page.
If you want to try it, the plugin is live in the ScrapeUnblocker dashboard and documented alongside the other plugins in the developer docs. Point it at a keyword and see what image search looks like as structured data.
Try ScrapeUnblocker free
95%+ success rate · from 0.55€ per 1,000 calls · 500 free requests on signup.