# Google Images Scraper (`dami_studio/google-images-scraper`) Actor

Google Images scraper: one row per image result with the thumbnail, the source page the image sits on, its domain, the title and the rank. No login. $0.40 per 1,000 images.

- **URL**: https://apify.com/dami_studio/google-images-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** SEO tools, Developer tools, Automation
- **Features:** Limited permissions
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.38 / 1,000 image results

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

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

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

**Type a search and get one row per Google Images tile**: the Google thumbnail, the page hosting the
image, that page's domain, the tile's title text and its rank in the results.

Read this before you buy, because it decides whether this is any use to you. Google stopped putting
the original file address in the Images page, so there is no link to the full-size file here. Every
row comes back with `imageUrl: null` and `imageUrlAvailable: false` rather than passing the
thumbnail off as the original. What you get is `thumbnailUrl` and `sourcePageUrl`.

| | |
|---|---|
| **Input** | One Google Images search |
| **Output** | One row per image tile: thumbnail, source page, its domain, title, rank |
| **Ceiling** | 100 images per run, across up to 3 pages |
| **Account needed** | None, and no Google API key |
| **Price** | $0.40 per 1,000 images on the Free plan, a little less on paid plans. The free plan's $5 a month covers about 12,500 |

### 🔍 What Google Images Scraper does

It runs your search against Google Images, reads the tile grid, and writes a row per tile.

Each row carries the thumbnail Google serves in the grid and its width and height, the page the image
sits on and that page's domain, the tile's title text, Google's own tile id, and the rank and page it
came from.

Set `maxPages` up to 3 to ask for more tiles. Duplicate tiles are removed across pages, so an image
appearing twice arrives once.

### 📋 What data you get from each Google Images result

| What you get | Field |
|---|---|
| The thumbnail Google serves in the grid, and its size | `thumbnailUrl`, `thumbnailWidth`, `thumbnailHeight` |
| The page the image sits on, and its domain | `sourcePageUrl`, `sourceDomain` |
| The tile's title text | `title` |
| Google's own id for the tile | `docId` |
| Rank within its page, and which page | `rank`, `page` |
| The search that produced it | `query` |
| The original file's address and size, which Google no longer gives, with a flag that says so | `imageUrl`, `width`, `height`, `imageUrlAvailable` |
| Whether SafeSearch was applied, which it never is | `safeSearchApplied` |

### ▶️ How to scrape Google Images

1. Open [Google Images Scraper](https://apify.com/dami_studio/google-images-scraper) and click **Try
   for free**.
2. Put your search into **Image search query**, replacing the example.
3. Set **Maximum images**. Twenty is a sensible first run.
4. Change **Language** and **Country** if you want another market's results, then click **Start**.
5. Download the dataset as JSON, CSV or Excel, or read it from the Apify API.

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

**$0.40 per 1,000 images** on the Free plan. Paid plans pay a little less: $0.395 on Starter, $0.39 on Scale and $0.385 on Business. On the free plan, the
$5 Apify gives you each month covers about 12,500 images.

`maxItems` caps the rows, so it also caps what a run can bill: set it to 20 and twenty rows is the
most you can be charged for.

Not charged as images: the sample row, every diagnostic row, duplicate tiles removed across pages,
and a search that comes back with nothing.

### 📥 What you give it

```json
{
  "query": "golden retriever puppy",
  "language": "en",
  "countryCode": "US",
  "maxItems": 20,
  "maxPages": 1
}
```

| Field | Default | What it is |
|---|---|---|
| `query` | none, the box starts at `red running shoes` | Your image search. Leave it empty and you get one uncharged sample row. |
| `language` | `en` | Google interface language, like `en`, `fr` or `de`. |
| `countryCode` | `US` | Two-letter country for localised results. |
| `maxItems` | `20` | Image rows to return, 1 to 100. It is also the most a run can bill you. |
| `maxPages` | `1` | Result pages to request, 1 to 3. More pages take longer. |
| `safeSearch` | `active` | **Not applied.** See below. |
| `enableProxyFallback` | on | On by default. Off, a search usually ends in a `NOT_SERVED` row with no images. |
| `proxyConfiguration` | leave it alone | Optional. Your own servers are used exactly as given, in the order listed. |

**`safeSearch` does nothing.** It is still in the form, and every value behaves the same: Google
returns a mostly unrelated tile set when the setting is sent, so it is left off and you get Google's
default filtering. Rows say so with `safeSearchApplied: false`. Do not build a content policy on
that field.

### 📤 What you get back

A real row from a run on 21 September 2026:

```json
{
  "ok": true,
  "rank": 1,
  "query": "golden retriever puppy",
  "page": 1,
  "title": "How to Train a Golden Retriever Puppy: Growth & Training Timeline",
  "imageUrl": null,
  "imageUrlAvailable": false,
  "thumbnailUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRUNLBzUGVp8D2IE6U-7oqMxVJ0xJaE1GFBpikkO40bOA&s=10",
  "thumbnailWidth": 678,
  "thumbnailHeight": 452,
  "sourcePageUrl": "https://www.akc.org/expert-advice/dog-breeds/golden-retriever-puppy-training-timeline/",
  "sourceDomain": "www.akc.org",
  "width": null,
  "height": null,
  "docId": "jUS0xT_ulT-SUM",
  "safeSearchApplied": false
}
```

| Field | How to read it |
|---|---|
| `thumbnailUrl` | The only image address you get. It is Google's cached thumbnail, not the original file. |
| `thumbnailWidth`, `thumbnailHeight` | The served thumbnail's shape, read from the tile. |
| `imageUrl`, `imageUrlAvailable` | `null` and `false` on the current layout. The field exists so a row never pretends otherwise. |
| `width`, `height` | The original file's dimensions. Also `null`, for the same reason. |
| `sourcePageUrl`, `sourceDomain` | The page carrying the image. This is what most people actually want. |
| `docId` | Google's own tile identifier, handy as a dedupe key. |

### 🧾 Reading the output

| Row | How to spot it | Charged |
|---|---|---|
| An image tile | `ok: true` and no `_sample` | yes |
| The sample row | `_sample: true` | no |
| A diagnostic | `ok: false` and an `errorCode` | no |

**The sample row is not representative of a real one.** It shows `imageUrl`, `width` and `height`
filled in, and real rows on the current layout never carry them. Run a one-image search to see the
truth.

| Code | What it means |
|---|---|
| `NO_RESULTS` | The page came back with no tiles on it. A very narrow search lands here. |
| `NOT_SERVED` | This search page was not served this run. Re-run it later. Runs before 13 October 2026 wrote `BLOCKED` or `JS_REQUIRED` here. |
| `RATE_LIMITED` | Google answered with a rate limit. Wait and try again. |
| `NETWORK` | Google was unreachable or the response never finished. |
| `TIME_LIMIT` | The run reached its time limit. The images found before it stay and are charged; give the run more time to get the rest. Even when the limit stopped it before any image came back, the run ends as succeeded, with an amber status message. |

The Overview table shows `imageUrl`, `width` and `height`, which are always empty, and hides
`thumbnailUrl` and `sourceDomain`, which are not. Read the dataset as JSON or export it, rather than
judging a run by that table.

### 💡 What people use it for

- Finding which sites carry a product photo, by reading `sourceDomain` across the whole result set.
- Building a shortlist of pages to visit for licensing, where the source page matters more than the
  file.
- Comparing what one search returns in `US` against `DE` or `JP`, tile for tile.
- Checking how your own pages rank in image results for a keyword, using `rank` and `sourceDomain`.

From an image search to the people behind the pages, in three steps:

1. Search your product's name here and copy the `sourceDomain` column.
2. Paste those domains into
   [Contact Details Scraper](https://apify.com/dami_studio/contact-details-scraper)'s `websites` for
   the emails and contact forms each site publishes.
3. Write to the ones using your pictures, about credit or a licence.

### 🚧 What it does not do

- **No original file addresses.** `imageUrl`, `width` and `height` are `null` on every row from the
  current layout. If your project needs the full-size file, open `sourcePageUrl` and find it there.
- **`safeSearch` is not applied**, whatever you set it to. `safeSearchApplied: false` on every row.
- **100 images and 3 pages per run.** There is no way to ask for the thousandth result.
- **A failure on page two or three throws away the earlier rows.** With `maxPages` above 1, a run
  that trips on a later page writes a diagnostic and no image rows. Keep it at 1 when one page is
  better than nothing.
- **One search per run.** Use a schedule or several runs for a keyword list.
- **It does not download images.** You get addresses and metadata, and what you do with them is
  yours to get right: licences, copyright and each site's terms are your responsibility.
- **Rows are a snapshot.** Image results reshuffle constantly.
- It is not an official Google tool. Dami's Studio is independent and is not affiliated with or endorsed by Google, or by any other company named on this page.

### 🧭 Which Google scraper do you need?

| If you want | Use |
|---|---|
| The web results page for a keyword: organic, ads, People Also Ask | [Google Search Results Scraper](https://apify.com/dami_studio/google-search-results-scraper) |
| What a search box suggests as people type | [Keyword Autocomplete Scraper](https://apify.com/dami_studio/keyword-autocomplete-scraper) |
| Interest in a keyword over time and by region | [Google Trends Scraper](https://apify.com/dami_studio/google-trends-scraper) |
| News articles with the publisher's real link | [Google News Scraper](https://apify.com/dami_studio/google-news-scraper) |
| Image results and the pages they sit on | This one |
| The ads a brand runs on Google | [Google Ads Transparency Scraper](https://apify.com/dami_studio/google-ads-transparency-scraper) |
| The photos on one Google Maps place, at the width you choose | [Google Maps Place Photos Scraper](https://apify.com/dami_studio/google-maps-place-photos-scraper) |
| Pins by keyword, with the link each one points at | [Pinterest Search Scraper](https://apify.com/dami_studio/pinterest-search-scraper) |

### ❓ Questions people ask

#### Can I get the full-size image file from Google Images?

Not from Google. The address is not in the page any more. Open `sourcePageUrl` and take it from the
page itself.

#### Why is `width` empty when `thumbnailWidth` is filled?

`thumbnailWidth` is the tile Google served. `width` would be the original file, and Google no longer
tells anyone what that is.

#### Do I need a Google API key?

No. Nothing to apply for and nothing to sign in to.

#### How many images can one search return?

Up to 100, across at most three pages. Google often runs out before that on a narrow search.

#### Can I call it from code or connect it to an AI assistant?

The [API tab](https://apify.com/dami_studio/google-images-scraper/api/python) has code for Python, JavaScript and the
CLI. MCP clients like Claude and ChatGPT use
`https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/google-images-scraper`; coding assistants can load [our
skill file](https://api.apify.com/v2/key-value-stores/BTBHU3DdiuoF4JOsK/records/apify-search-app-stores-SKILL.md). All
three bill your Apify account at the same price.

#### Is scraping Google Images legal?

The rows are public search metadata and addresses. The images themselves belong to whoever made
them, so check licences and each site's terms before reusing anything. Apify's write-up on
[the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) is a good starting
point, and we are not lawyers.

### 🆘 If something breaks

Open the **Issues** tab on the actor page. Send the search and the run ID. The `errorCode` on the
diagnostic row usually names the problem on its own.

# Actor input Schema

## `query` (type: `string`):

Keywords to search in Google Images, for example "red running shoes". Leave empty to receive one representative uncharged sample row.

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

Currently NOT applied. Google returns a mostly unrelated tile set for any value of the safe parameter on the Images surface, so the parameter is omitted and Google default filtering is used. Rows carry safeSearchApplied: false.

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

Google interface language code such as en, fr, or de.

## `countryCode` (type: `string`):

Two-letter Google country code used for localized results, such as US, CA, or GB.

## `maxItems` (type: `integer`):

Maximum successful image rows to return from the search, from 1 to 100.

## `maxPages` (type: `integer`):

Maximum number of bounded Google Images result pages to request, from 1 to 3. More pages take longer.

## `enableProxyFallback` (type: `boolean`):

On by default. Switched off, most searches come back with no images.

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

Optional. Leave this alone unless you need the run to go out through a particular network. Your own proxy servers are used exactly as given.

## Actor input object example

```json
{
  "query": "red running shoes",
  "safeSearch": "active",
  "language": "en",
  "countryCode": "US",
  "maxItems": 20,
  "maxPages": 1,
  "enableProxyFallback": true
}
```

# Actor output Schema

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

One dataset row per successful image result, plus an uncharged sample or diagnostic row.

# 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 = {
    "query": "red running shoes"
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/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 = { "query": "red running shoes" }

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/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 '{
  "query": "red running shoes"
}' |
apify call dami_studio/google-images-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/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/TcmFOlrfq7o218Iai/builds/xbJU8L3oaECb3pV2p/openapi.json
