# Google Images Scraper — Site, Country & Language Filter (`scrapier/google-images-scraper`) Actor

Google Images Scraper: Search and extract image results with titles, URLs, source websites, thumbnails, and metadata. Filter results by site, country, and language to support visual research, competitor analysis, content discovery, and localized image intelligence.

- **URL**: https://apify.com/scrapier/google-images-scraper.md
- **Developed by:** [Scrapier](https://apify.com/scrapier) (community)
- **Categories:** Lead generation, Social media, Videos
- **Stats:** 16 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$24.99/month + usage

To use this Actor, you pay a monthly rental fee to the developer. The rent is subtracted from your prepaid usage every month after the free trial period. You also pay for the Apify platform usage, which gets cheaper the higher Apify subscription plan you have.

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

## 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

### Google Images Scraper — Extract Photos by Site, Country & Language

Turn a list of keywords into structured Google Images results — direct image links, thumbnails, source pages, and titles — restricted to the websites, country, and language you choose. Every match streams into your Apify dataset as a typed JSON row the moment it's collected, ready to load into a spreadsheet, pass to an LLM, or feed a monitoring pipeline. Leave the targeting fields empty and it behaves like a plain global Google Images search.

### 🖼️ What is the Google Images Scraper — Site, Country & Language Filter?

This Actor queries Google Images (`google.com/search?udm=2`) for one or more keywords and returns every unique image it finds as a structured row — image URL, thumbnail, dimensions, source page, and site of origin. No Google account, API key, or login is required: it runs as an anonymous search request through Apify Proxy. What sets this build apart from a plain keyword search is the targeting layer — you can restrict results to specific domains, pin the search to a regional Google, force a results language, and toggle SafeSearch, all per run, with no external setup.

It exposes these real query controls:

- 🔤 Multiple keywords per run, processed one after another
- 🎯 A per-keyword image cap (`maxImages`)
- 🔗 Site restriction to one or more domains (`siteDomains`)
- 🌎 Country targeting (`country`, appended as Google's `gl` parameter)
- 🗣️ Language targeting (`language`, appended as Google's `hl` parameter)
- 🛡️ SafeSearch on/off (`safeSearch`, appended as Google's `safe` parameter)

### 📊 What data can you get with the Google Images Scraper?

Every run returns one result type: individual image records, each pairing the image itself with the page it was found on and the domain that hosted it.

| Result Type | Extracted Fields | Primary Use Case |
| --- | --- | --- |
| Image result | `query`, `imageUrl`, `imageWidth`, `imageHeight`, `thumbnailUrl`, `thumbnailWidth`, `thumbnailHeight`, `contentUrl`, `origin`, `matchedDomain`, `title` | Visual datasets, creative/catalog sourcing, market and competitor research |

#### Site, Country & Language Targeting

This is the layer that separates this build from a plain Google Images fetch. `siteDomains` rewrites your keyword into a Google `site:` query — one domain becomes `keyword site:domain.com`, multiple domains become `keyword (site:d1 OR site:d2 ...)` — so results are pulled only from the sites you name. `country` and `language` pin the request to a specific regional Google and interface language before any parsing happens, so the images and their surrounding metadata reflect that locale rather than whatever Google infers from the request's IP. Every row carries a `matchedDomain` field so you can verify, per image, that the site restriction actually held:

```json
{
  "query": "modern living room",
  "imageUrl": "https://i.pinimg.com/originals/aa/bb/cc/example.jpg",
  "contentUrl": "https://www.pinterest.com/pin/123456789/",
  "origin": "www.pinterest.com",
  "matchedDomain": "www.pinterest.com"
}
```

### 🔍 How does the Google Images Scraper differ from the official Google API?

Google's own **Custom Search JSON API** can return image results, but it comes with quota, credential, and setup requirements this Actor does not have.

| Feature | Google Custom Search JSON API | Google Images Scraper — Site, Country & Language Filter |
| --- | --- | --- |
| Credentials required | A Google Cloud API key plus a configured Programmable Search Engine ID | An Apify account only — no Google credentials |
| Free quota | 100 queries/day free; $5 per 1,000 additional queries, up to 10,000/day (Google Custom Search JSON API documentation, accessed 2026-07-30) | No daily query cap — priced per `row_result` image row via Apify pay-per-event |
| Results per query | Up to 100 results total per query (Google Custom Search JSON API documentation, accessed 2026-07-30) | Up to `maxImages` (max 100,000) per query, broadened automatically until Google's index for that keyword is exhausted |
| Site restriction | The Programmable Search Engine must be pre-configured to restrict which sites it searches | Pass `siteDomains` per run — no engine setup, changeable on every run |
| New customer availability | Closed to new customers; existing customers must migrate off it by January 1, 2027 (Google Custom Search JSON API documentation, accessed 2026-07-30) | Open to any Apify account, no migration deadline |
| Output delivery | JSON in the REST response | JSON rows streamed live into an Apify dataset, exportable to JSON, CSV, or Excel |

The Custom Search API suits teams that already hold Google Cloud credentials and can live with its 100-result ceiling per query. This Actor suits ad hoc and bulk image research — no Google Cloud project to provision, and results stream straight into a dataset you can export or pipe into another tool.

### 🚀 How to scrape Google Images with this Actor

1. Open the Actor's page on the Apify Store and click **Run**, or start it via the Apify API / `apify_client`.
2. Enter your search phrases in `queries` — the only required field, one phrase per line.
3. Set the real query controls that apply: `siteDomains` to restrict sites, `country` and `language` to localize, `safeSearch` to filter explicit content, `maxImages` to cap results per keyword.
4. Start the run.
5. Stream or download results as JSON, CSV, or Excel from the run's dataset — rows appear while the run is still in progress.

```json
{
  "queries": ["modern living room", "minimalist kitchen"],
  "maxImages": 50,
  "siteDomains": ["pinterest.com", "wikipedia.org"],
  "country": "gb",
  "language": "en",
  "safeSearch": "active"
}
```

#### How to run multiple queries in one job

`queries` is an array — add as many search phrases as you need, one per line in the editor. Every phrase runs in the same job and inherits the same `siteDomains`, `country`, `language`, `safeSearch`, and `maxImages` settings. Queries are processed one after another, not in parallel, and each keyword's original text (before any `site:` filter is appended) is what ends up in the `query` column of its rows.

### ⬇️ Input

| Parameter | Required | Type | Description | Example Value |
| --- | --- | --- | --- | --- |
| `queries` | Yes | array (`stringList`) | List of search phrases (e.g. nature, product shots, logos). One query per line in the editor. | `["nature", "product shots"]` |
| `maxImages` | No | integer (default `10`, minimum `1`, maximum `100000`) | Cap how many unique images to keep for each keyword. | `50` |
| `siteDomains` | No | array (`stringList`) | Only return images hosted on / sourced from these domains. One domain → `site:domain`. Multiple → `(site:d1 OR site:d2 ...)`. Leave empty for no restriction. | `["pinterest.com", "wikipedia.org"]` |
| `country` | No | string (`select`, default `""`) | Regional Google to search from (appends `&gl=`). Leave empty for default. | `"us"` |
| `language` | No | string (`select`, default `""`) | Interface / results language (appends `&hl=`). Leave empty for default. | `"en"` |
| `safeSearch` | No | string (`select`, default `""`) | Filter explicit results (appends `&safe=`). Leave empty for default. | `"active"` |
| `proxyConfiguration` | No | object (`proxy` editor) | Keep the default proxy selection for best results. | `{"useApifyProxy": true, "apifyProxyGroups": ["GOOGLE_SERP"]}` |

`country` accepts: `""` (— Default (none) —), `us` (United States), `gb` (United Kingdom), `de` (Germany), `fr` (France), `in` (India), `br` (Brazil), `jp` (Japan), `ca` (Canada), `au` (Australia), `es` (Spain), `it` (Italy), `nl` (Netherlands), `mx` (Mexico), `ru` (Russia).

`language` accepts: `""` (— Default (none) —), `en` (English), `es` (Spanish), `de` (German), `fr` (French), `hi` (Hindi), `pt` (Portuguese), `ja` (Japanese), `it` (Italian), `nl` (Dutch), `ru` (Russian), `zh-CN` (Chinese (Simplified)), `ar` (Arabic).

`safeSearch` accepts: `""` (— Default (none) —), `active` (Active — filter explicit), `off`.

**Pitfall to avoid:** leaving `country` or `language` blank does not mean "no locale parameter" the way the "— Default (none) —" label suggests — the Actor falls back to `gl=us` and `hl=en` internally for every request, so a blank run still queries United States / English Google. Set them explicitly if you need a different locale. For `siteDomains`, use the bare domain (`pinterest.com`), not a full URL (`https://www.pinterest.com/`) — the value is inserted directly after `site:`.

### ⬆️ Output

Each row is typed, normalized JSON with a consistent schema across every run — no fields are added or dropped between rows. Every pushed row is charged as one `row_result` event; the Actor pushes no separate error or accounting rows, so nothing needs to be filtered out of the dataset. Results are streamed to the dataset in real time and can be exported as JSON, CSV, or Excel from the Apify Console or API.

#### Scraped results

```json
[
  {
    "query": "minimalist kitchen",
    "imageUrl": "https://cdn.example.com/photos/kitchen-01.jpg",
    "imageWidth": 1600,
    "imageHeight": 1067,
    "thumbnailUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:abc123",
    "thumbnailWidth": 259,
    "thumbnailHeight": 194,
    "contentUrl": "https://www.example-design-blog.com/minimalist-kitchens",
    "origin": "www.example-design-blog.com",
    "matchedDomain": "www.example-design-blog.com",
    "title": "20 Minimalist Kitchen Ideas for 2026"
  },
  {
    "query": "minimalist kitchen",
    "imageUrl": "https://i.pinimg.com/originals/12/34/56/kitchen-white.jpg",
    "imageWidth": 1200,
    "imageHeight": 1500,
    "thumbnailUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:def456",
    "thumbnailWidth": 156,
    "thumbnailHeight": 195,
    "contentUrl": "https://www.pinterest.com/pin/987654321/",
    "origin": "www.pinterest.com",
    "matchedDomain": "www.pinterest.com",
    "title": "All-white minimalist kitchen inspiration"
  },
  {
    "query": "minimalist kitchen",
    "imageUrl": "https://upload.wikipedia.org/wikipedia/commons/kitchen-interior.jpg",
    "imageWidth": 1920,
    "imageHeight": 1280,
    "thumbnailUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ghi789",
    "thumbnailWidth": 225,
    "thumbnailHeight": 150,
    "contentUrl": "https://en.wikipedia.org/wiki/Kitchen",
    "origin": "en.wikipedia.org",
    "matchedDomain": "en.wikipedia.org",
    "title": "Kitchen - Wikipedia"
  }
]
```

### 📈 How can I use the data extracted with this Actor?

- **🎨 Creative and content teams:** pull `imageUrl` and `thumbnailUrl` for mood boards, reference decks, or blog imagery sourced from named domains via `siteDomains`.
- **🤖 AI engineers and LLM developers:** an agent issues a query, receives the structured JSON rows, and passes `imageUrl`/`contentUrl` to a model as grounded visual context or citation links.
- **📊 Market researchers:** compare `origin` and `matchedDomain` across a keyword set to see which sites dominate image results for a term, region, or language.
- **🛒 Catalog and e-commerce teams:** restrict `siteDomains` to supplier or marketplace sites to source reference product imagery without browsing each site manually.

### 🔁 How do you monitor site image coverage over time?

Run the same keyword set, `siteDomains`, `country`, and `language` on a schedule and compare the `imageUrl` and `contentUrl` sets between runs. A new `imageUrl` that wasn't in the previous run's results means Google has indexed a new image on that site for that keyword; a `contentUrl` that disappears means the page was removed, de-indexed, or the image was replaced. Diffing on `imageUrl` (the stable identifier for a given image) is more reliable than diffing on `title`, which can change without the underlying image changing.

A practical loop: schedule a run across your keyword list with fixed `siteDomains`/`country`/`language`, store each run's `imageUrl` set, and alert when the diff against the previous run crosses a threshold you care about — a competitor's catalog domain suddenly gaining dozens of new indexed images, for example. Use the Apify Console's **Schedule** feature to trigger runs automatically; there is no built-in scheduler inside the Actor itself.

### 🔌 Integrate this Actor and automate your workflow

Google Images Scraper — Site, Country & Language Filter works with any language or tool that can send an HTTP request through the Apify API.

#### REST API with Python

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")

run = client.actor("<username>/google-images-scraper-site-country-and-language-filter").call(
    run_input={
        "queries": ["minimalist kitchen"],
        "maxImages": 25,
        "siteDomains": ["pinterest.com"],
        "country": "us",
        "language": "en",
    }
)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["imageUrl"], item["matchedDomain"])
```

#### Scheduled monitoring and delivery

Set up a recurring **Schedule** in the Apify Console to re-run the same input on a cadence, then pull new rows via the Apify API or `apify_client` after each run, or wire an Apify **webhook** to fire when a run finishes so a downstream system is notified without polling.

### ⚖️ Is it legal to scrape Google Images results?

Yes — scraping publicly accessible search results is generally legal; this Actor returns only image links, thumbnails, dimensions, and page metadata that any visitor to Google Images can already see. In *hiQ Labs v. LinkedIn* (9th Cir. 2019, cert. denied 2022), the court held that scraping publicly accessible web data does not violate the U.S. Computer Fraud and Abuse Act. This Actor extracts search-result metadata about images and pages, not personal profile data, so the relevant framework is Google's and the source sites' Terms of Service and database-rights considerations, not GDPR/CCPA. Scraping for one-off research or monitoring carries a different risk profile than scraping at scale to train AI models or to republish images commercially — the latter raises copyright questions this Actor does not resolve for you, since it returns links and metadata, not the image files themselves. Consult your legal team for commercial use cases involving bulk data storage.

### ❓ Frequently asked questions

#### How do I get Google Images results for a specific country or language?

Set `country` (Google's `gl` parameter) and `language` (Google's `hl` parameter) to any of the schema's supported values. Leaving both blank does not skip localization — the Actor still sends `gl=us` and `hl=en` by default, so you'll get United States / English results unless you set these explicitly.

#### Can I limit how many images come back, or filter explicit content?

Yes. `maxImages` caps unique images kept per keyword (1–100,000, default 10), and `safeSearch` can be set to `active` to filter explicit results or `off` to disable filtering; leaving it blank applies no `safe` parameter at all.

#### How does this Actor handle Google's anti-bot measures?

It sends requests with a Chrome TLS/HTTP fingerprint (via `curl_cffi`'s browser impersonation) through Apify Proxy's `GOOGLE_SERP` proxy group, detects Google's block/CAPTCHA page by response size and content, and retries each request up to 3 times with a short backoff and a fresh proxy IP before giving up on that request.

#### Does the `matchedDomain` field confirm my site restriction worked?

Yes. When you set `siteDomains`, every returned row's `matchedDomain` field shows the exact domain the image was sourced from, so you can verify per-row that results actually came from the sites you specified rather than trusting the query alone.

#### How many images does this Actor return per query?

Up to `maxImages` per keyword (maximum 100,000). It can return fewer: the Actor broadens each keyword across autocomplete-derived related terms and Google's own image search facets (color, type, size, aspect ratio, time range) to reach your target, but stops broadening a keyword after 14 consecutive fetches add no new unique image — meaning Google's index for that keyword and site/locale combination is exhausted.

#### How do I monitor image coverage for a keyword or site over time?

Run the same keyword set and targeting fields on a schedule, keep the `imageUrl` set from each run, and diff it against the previous run to see what's new or gone. See "How do you monitor site image coverage over time?" above for the full workflow.

#### Does this Actor work with Claude, ChatGPT, and AI agent frameworks?

It's callable as an HTTP endpoint through the Apify API by any agent framework — an agent can trigger a run, poll or wait for the dataset, and pass the returned `imageUrl`/`contentUrl`/`title` fields to a model as grounded context before generating an answer.

#### Can I use this Actor without managing proxies or Google credentials?

Yes. Apify Proxy is preconfigured (the `GOOGLE_SERP` proxy group) and handles IP rotation automatically — you only need an Apify account. No Google account, API key, or cookies are required.

#### Does this Actor download the actual image files?

No. It returns image URLs and metadata (dimensions, source page, title) — not the binary image files. Pass `imageUrl` to a downloader Actor or your own script if you need the files themselves.

### 💬 Your feedback

Found a bug or a field that doesn't match what's documented here? Open an issue directly from this Actor's page in the Apify Console — the Issues tab reaches the Scrapier team, and it's the fastest way to get a fix or an answer.

# Actor input Schema

## `queries` (type: `array`):

✍️ List of search phrases (e.g. nature, product shots, logos). One query per line in the editor.

## `maxImages` (type: `integer`):

🎚️ Cap how many unique images to keep for each keyword. The log shows progress toward this goal in real time.

## `siteDomains` (type: `array`):

🌐 Only return images hosted on / sourced from these domains. One domain → site:domain. Multiple → (site:d1 OR site:d2 ...). Leave empty for no restriction.

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

🗺️ Regional Google to search from (appends \&gl=). Leave empty for default.

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

🈳 Interface / results language (appends \&hl=). Leave empty for default.

## `safeSearch` (type: `string`):

🔞 Filter explicit results (appends \&safe=). Leave empty for default.

## `proxyConfiguration` (type: `object`):

⚙️ Keep the default proxy selection for best results.

## Actor input object example

```json
{
  "queries": [
    "nature"
  ],
  "maxImages": 10,
  "siteDomains": [
    "pinterest.com",
    "wikipedia.org"
  ],
  "country": "",
  "language": "",
  "safeSearch": "",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "GOOGLE_SERP"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All scraped items in the Actor's default dataset.

# 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 = {
    "queries": [
        "nature"
    ],
    "siteDomains": [
        "pinterest.com",
        "wikipedia.org"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "GOOGLE_SERP"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapier/google-images-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 = {
    "queries": ["nature"],
    "siteDomains": [
        "pinterest.com",
        "wikipedia.org",
    ],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["GOOGLE_SERP"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapier/google-images-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 '{
  "queries": [
    "nature"
  ],
  "siteDomains": [
    "pinterest.com",
    "wikipedia.org"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "GOOGLE_SERP"
    ]
  }
}' |
apify call scrapier/google-images-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapier/google-images-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/xW2T6HK1IDcUxPqV5/builds/0zvwcUOEirF1qikoe/openapi.json
