Product teams often need one question answered: which images show up when shoppers search this product phrase, and from which sites? Building that yourself means wiring up a search source, handling country and language codes, removing duplicate URLs, and deciding what to do when a search comes back empty.
Usually you don't need the image files. For assortment research, marketplace checks or a creative brief, the useful output is metadata: the image URL, the page it came from, the site, the title, the rank, and the pixel size.
This walkthrough uses SteadyScrape's Google Images API Actor on Apify. It returns that metadata as JSON for public, non-personal keywords. It does not download full files, rehost or license images. A result row grants no reuse, training or copyright rights.
What a run returns
Each keyword writes one status row and one image row per result, up to 100.
| Field | What it means |
|---|---|
rank |
Position in the image results |
imageUrl, thumbnailUrl
|
Source image URL and Google's thumbnail |
sourcePageUrl, sourceDomain, sourceName
|
The page that shows the image, its domain, and the site name Google shows |
title, altText
|
Result title and alt text |
width, height
|
Pixel size, read from the image file header. Null when it couldn't be read |
queryStatus |
success, partial, empty, timeout, failed, blocked_operator, not_run, and more |
relatedSearches, googleImagesUrl
|
On status rows: related searches and a link to the same Google Images page |
Where width and height come from
The search results don't include pixel sizes. So the Actor asks each image host for only the first bytes of the file (an HTTP range request) and stops reading as soon as the size is in the header. It reads PNG, JPEG, GIF, WebP, BMP and AVIF, contacts public hosts only, and spends about 12 seconds per keyword on this step.
Some hosts refuse range requests or answer slowly, so expect a share of nulls. In my test run for blue ceramic bowl, 51 of 100 images got a size, reading about 165 KB in total. You can turn the step off with "fillDimensions": false for the fastest runs. It never changes the status or the price.
Run it from Python
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("steady-scrape/google-images-api").call(
run_input={
"keywords": ["red ceramic mug", "blue ceramic bowl"],
"country": "us",
"language": "en",
"depth": 100,
}
)
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
if row["recordType"] == "image":
print(row["rank"], row["sourceName"], row["width"], row["height"], row["imageUrl"])
else:
print("STATUS", row["keyword"], row["queryStatus"], row["imageCount"])
Need a different country per keyword? Use the advanced form:
{
"queries": [
{ "keyword": "red ceramic mug", "country": "us", "language": "en" },
{ "keyword": "rote Keramiktasse", "country": "de", "language": "de" }
]
}
Want to try it with no search? "dryRun": true returns labeled sample rows and nothing is charged.
A real run
A single keyword (blue ceramic bowl, US, English, depth 100):
- 100 image rows plus a status row with 20 related searches
- search took about 28 seconds, then about 13 seconds of size fill-in
- 51 of the 100 images got a width and height
- the same run included
site:example.com mug, which was rejected asblocked_operatorand not charged - charged: one $0.010 query event plus the $0.002 run event = $0.012
What it costs
-
$0.010 per keyword that returns at least one image (including a
partialresult with at least one image) - $0.002 once per run, only if at least one keyword returned images
- Empty, failed and timed-out searches are free, and so is test mode
| What you run | Cost |
|---|---|
| 1 keyword with images | $0.012 |
| 10 keywords with images in one run | $0.102 |
| 10 keywords, 2 of them find nothing | $0.082 |
| a run where nothing is found | $0.000 |
Apify also adds its standard apify-actor-start event ($0.00005 per run at the default 256 MB). You can set a maximum cost per run, and the Actor stops sending new searches before it would go over.
Limits worth knowing
- Up to 10 keywords per run, up to 100 images each, one search at a time.
- Each search can take up to about 95 seconds. A search that may already have been answered is never sent twice, so you aren't charged twice.
- Advanced operators (
site:, a leading minus and similar) are rejected for free. Don't submit person or face lookups. Emails, phone numbers and profile links are rejected. - Live search needs a paid Apify plan.
- Chinese must be
zh-CNorzh-TW.
FAQ
Does this download the images? No. It returns links. With size fill-in on, it reads only the first bytes of each file.
Can I use the images in my store or for training? Not based on this output. Rows are search metadata, so check each source page for rights.
What does partial mean? The search returned images, but a few results were incomplete and were left out. It's charged like a success because you got images.
Can I schedule it? Yes. It's a normal Apify Actor, so you can use Apify schedules, the API, webhooks, Make, Zapier, n8n, or the Apify MCP server for AI agents.
Try it here: Google Images API on Apify. Results come from Google Images via the DataForSEO API. The Actor is not affiliated with Google.
Top comments (0)