# Google Images Scraper - up to 100K per Keyword (`thodor/google-image-scraper`) Actor

Google Images scraper tool and Google Image Search API alternative: up to 100,000 full-size image URLs per keyword with pixel dimensions and source pages. No API key.

- **URL**: https://apify.com/thodor/google-image-scraper.md
- **Developed by:** [Thodor](https://apify.com/thodor) (community)
- **Categories:** SEO tools, Automation, Other
- **Stats:** 27 total users, 3 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 unique image scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

A **Google Images scraper tool** that pulls **up to 100,000 full-size image URLs per keyword**, where a normal Google Images scraper stops at the first hundred thumbnails. Type a keyword and get every image's original URL with true pixel dimensions, source page, and caption, then **load them into a spreadsheet** as CSV, Excel, or JSON. No API key, no browser, no Google Cloud project.

There is no official Google Image Search API to call, and the SERP APIs that stand in for it return roughly the first 100 results per query. This actor is the **Google Image Search API alternative** for volume work: AI training image datasets, computer vision sourcing, e-commerce image research, and brand monitoring across countries. Scraping Bing instead? The [Bing Image Search API Scraper](https://apify.com/thodor/bing-images) does the same job on Bing.

### 📋 How to scrape Google Images

1. Type a keyword in **Search Query**.
2. Set **Max Results** to the number of images you want. It caps the run and the bill.
3. Click **Start**.
4. Open the **Output** tab and click **Export** for CSV, Excel, JSON, or HTML.

A 250-image sample finishes in seconds.

### 🎁 So what do you get?

| 🖼️ Full-resolution image URL | 📐 Width and height of the original | 🔗 Source page URL |
| --- | --- | --- |
| 🏷️ Caption, the source page's title | 🌍 Which Google market surfaced it | 🧭 Found by search or via related images |
| ⚡ Google's thumbnail URL | 🔍 Link to the visually similar images | 🔁 Deduplicated across paths |

### ⚖️ Compared to SerpApi and other Google Images scrapers

| | SerpApi, Zenserp, typical scrapers | This actor |
|---|---|---|
| 🖼️ Images per keyword | ❌ ~100, first page only | ✅ up to ~100,000 |
| 🔍 Related images | ❌ Never opened | ✅ Opened for every result |
| 🌍 Markets | ❌ One | ✅ 15 |
| 🔗 Image URL | ❌ gstatic thumbnail, ~250px | ✅ Full-resolution original |
| 📐 Width and height | ❌ The thumbnail's | ✅ The original's |
| 🔑 Access | ❌ API key, per-request plans | ✅ Register on Apify, $5 free monthly credit |
| 💵 Billing | Per request | ✅ Per unique result |

**Why they stop early.** Google's pagination dies around 250 images. Getting past it means opening the "visually similar" page behind each result, which normally needs a browser. Its address turns out to be computable, so this actor fetches it over plain HTTP instead.

**Why the URLs are full-resolution.** The original is never in the `<img>` tag, only in a JSON blob behind it, one array after the thumbnail. Anything reading rendered HTML sees the thumbnail and stops.

```
["https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9%E2%80%A6", 259, 194]   <- what others return
["https://upload.wikimedia.org/%E2%80%A6/2025_Bart_De_Wever.jpg", 333, 250]   <- what you get
```

### 🎯 Three things people run this for

| | How |
|---|---|
| 🧠 **AI training image datasets** | One keyword per class label, then the resolution filter below keeps only images big enough to train on, before you download a single file. |
| 🛍️ **E-commerce image research** | Batch product keywords and export one spreadsheet of full-size images with the page each one came from. |
| 📈 **Brand monitoring across countries** | Run the same keyword with a fixed country to see what really ranks there, so an image that only ranks in Brazil stays out of your German report. |

### 📥 Input

```json
{"search_query": "golden retriever", "max_results": 5000}
```

- `search_query`: the keyword. Required.
- `max_results`: default `200`. Hard cap on images and on billing.
- `get_related_images`: default `true`. Also collects the visually similar images behind every result.
- `country`: default `US`. The Google market to rank for, 50 supported. Always searched first.
- `expand_markets`: default `true`. Sweeps the other 14 markets once `country` is exhausted. Set `false` to keep every result ranked for `country`.
- `language`: default `en`. Interface language.

There is no fixed cap. Both switches are on by default, so the one number that decides your run is `max_results`:

| What you want | Images | Switch on |
|---|---|---|
| 🌍 **As many as possible, anywhere** | **~100,000** | Related images **+** Expand markets ✅ |
| 📍 **Everything for one country** | **~20,000** | Related images ✅, Expand markets ❌ |
| ⚡ **A quick sample** | **~250** | Leave `max_results` at 250 |

Measured on `cat`: 19,874 from one market, 28,986 once a second market is added. The 100,000 is the theoretical maximum across all fifteen markets. Your own `country` is always searched first and supplies ~250 on its own, the same set you'd see typing the query into Google Images, so a low cap gives you a quick look at the output shape before a large run.

#### 🌍 As many as possible, don't care where from

Sweeps all fifteen markets and stops at `max_results`. Every row records its `market`, so you can still filter later. The output no longer represents any single market, which is right for datasets and wrong when local ranking is the point.

```json
{"search_query": "golden retriever", "max_results": 100000,
 "get_related_images": true, "expand_markets": true}
```

#### 📍 Everything for one country

Results stay ranked for one market, for SEO checks and brand monitoring.

```json
{"search_query": "wanderschuhe", "max_results": 20000,
 "country": "DE", "language": "de", "get_related_images": true}
```

### 📤 Output

One flat row per image, deduplicated.

![Google Images scraper output: full-resolution image URLs with pixel dimensions, source pages and captions for building AI training image datasets](https://api.apify.com/v2/key-value-stores/LHcvkclm26dcJvwP1/records/google-images-api-example-output.png)

```json
{
  "image_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/2025_Bart_De_Wever.jpg",
  "thumbnail_url": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR0OZnTrRQLi8&s",
  "width": 250,
  "height": 333,
  "page_url": "https://es.wikipedia.org/wiki/Bart_De_Wever",
  "title": "Bart De Wever - Wikipedia, la enciclopedia libre",
  "search_query": "bart de wever",
  "market": "US",
  "depth_level": 0
  // HIDDEN: related_link
}
```

> ⚠️ **`title` is the source page's title, not alt text.** Google doesn't ship the `alt` attribute in this payload; fetch `page_url` if you need it. Present on 100% of direct results and 87% of related-image results.

#### Fields

| Field | Description |
|---|---|
| `image_url` | Full-resolution original on the origin server |
| `thumbnail_url` | Google's gstatic thumbnail |
| `width`, `height` | Pixel dimensions of the original |
| `page_url` | Page hosting the image |
| `title` | That page's title, the caption Google prints under the result |
| `related_link` | Link to visually similar images |
| `search_query` | Keyword used |
| `market` | Google market that surfaced this image |
| `depth_level` | `0` = found by the search, `1` = found via related images |

### 🧠 Build an AI training image dataset

Training a model needs volume plus enough metadata to filter and attribute, and a standard SERP API gives you ~100 results and a thumbnail URL, which is neither. Here the width and height are the original's, so you can keep only images big enough to train on before downloading any of them:

```python
usable = [r for r in items if (r["width"] or 0) >= 768 and (r["height"] or 0) >= 768]
```

An image reached through many paths is emitted once, so the set doesn't over-weight popular images. `depth_level` and `market` let you balance or stratify it, and `page_url` plus `title` are what dataset documentation and licence review need.

### ⚙️ Use it as a Google Image Search API

Every run is an HTTP endpoint: POST the same JSON as the form and the image rows come back in the response body.

#### Python

```python
import requests

resp = requests.post(
    "https://api.apify.com/v2/acts/thodor~google-image-scraper/run-sync-get-dataset-items",
    params={"token": "YOUR_APIFY_TOKEN"},
    json={"search_query": "golden retriever", "max_results": 5000},
)
items = resp.json()
```

#### Node.js

```javascript
import axios from "axios";

const { data } = await axios.post(
  "https://api.apify.com/v2/acts/thodor~google-image-scraper/run-sync-get-dataset-items",
  { search_query: "golden retriever", max_results: 5000 },
  { params: { token: process.env.APIFY_TOKEN } }
);

console.log(data.length, data[0].image_url);
```

#### curl

```bash
curl -X POST "https://api.apify.com/v2/acts/thodor~google-image-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"search_query":"golden retriever","max_results":5000}'
```

Swap `run-sync-get-dataset-items` for `runs` to fire async with a webhook when a large run outlives the 5-minute sync window. The `apify-client` SDK works too, in Python and JavaScript, and the n8n, Make, and Zapier integrations take the same input.

> 💡 **Tip:** no need to write the JSON by hand. Fill in the form on the Input tab, switch the editor from **Form** to **JSON**, and copy the result into your code.

### 💰 How much does it cost to scrape Google Images?

Billing is per unique result, at the rate on the price card on this page. Duplicates and rows without a resolved full-size URL are free. `max_results` is both the cap and the brake: a run capped at 5,000 bills at most 5,000 images, so set it to the dataset size you actually want.

### ❓ FAQ

**Is there an official Google Image Search API?**
No. Google discontinued it in 2011. The nearest option, the Custom Search JSON API, returns at most 10 images per request on a 100-query daily free tier.

**Can I use this Google Images scraper for free?**
Yes. Registering on Apify comes with $5 of free platform credit every month, no credit card needed, enough for real test runs.

**Does it download the image files?**
No. It returns full-resolution URLs and metadata; downloading is a loop over `image_url` in your own script.

**Why doesn't it go deeper than one level of related images?**
It reaches more, but relevance drops off by the third or fourth level and you start collecting things that aren't your query. That trade shouldn't be made for you. If you need it, open a ticket on the Issues tab and I'll enable it.

**Can I use the images commercially?**
The actor returns URLs and metadata, not licences. Check terms per source via `page_url`. Nothing here grants rights to the underlying files.

**What if Google rate-limits a run?**
Everything collected is saved and you're only billed for unique results. For very large jobs, several smaller runs beat one enormous one.

### 🛟 Support

Something not working, or a field missing? Message me in the Issues tab and I'll look into it quickly. I'm a solo dev, so don't hesitate.

Need to know where one image appears online, rather than every image for a keyword? That's the [Reverse Image Search API](https://apify.com/thodor/google-lens-exact-matches).

- Thodor

# Actor input Schema

## `search_query` (type: `string`):

The search term to use on Google Images

## `max_results` (type: `integer`):

Maximum number of images to scrape

## `get_related_images` (type: `boolean`):

Follow visually similar image links to massively expand results (up to 30k images from a single query)

## `country` (type: `string`):

Which country's results to rank for (Google's gl parameter). Results stay ranked for this market unless you raise Market Expansion.

## `expand_markets` (type: `boolean`):

Sweep additional Google markets (GB, DE, FR, IN, JP, BR...) for more images of the same search. Each market re-ranks the same query and related pages overlap only 4-28% between markets, so this multiplies the total — but results are no longer specific to your chosen Country. Leave off to keep every result ranked for that one market. Max results still caps the run.

## `language` (type: `string`):

Google interface language. Defaults to the country's own language.

## Actor input object example

```json
{
  "search_query": "cat",
  "max_results": 200,
  "get_related_images": true,
  "country": "US",
  "expand_markets": true,
  "language": "en"
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "search_query": "cat"
};

// Run the Actor and wait for it to finish
const run = await client.actor("thodor/google-image-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "search_query": "cat" }

# Run the Actor and wait for it to finish
run = client.actor("thodor/google-image-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "search_query": "cat"
}' |
apify call thodor/google-image-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,thodor/google-image-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/3bAGX8Fjcj0lfVPbw/builds/xLLUZsTMcXT4TkGB6/openapi.json
