Skip to content
CrawlerData
Menu
Guides

Is there a Google Images API? Search and download images with Python

Google has no public Images API. Get Google Images results as JSON instead: up to 100 images per request, with size filters and downloads in Python.

CrawlerData teamPublished 6 min read

Contents

If you are looking for a Google Images API, the short version is: there isn’t a public one, and the one that came closest is closing. This guide explains where that leaves you, then shows how to get Google Images results as JSON in Python, filter them by size and download the files.

Every response excerpt below comes from requests we ran in October 2026. Google’s results change by the minute, so yours will differ.

What happened to the Google Images API?

The one Google product that offered image search to developers is on its way out. Per Google’s own overview page, checked in October 2026, the Custom Search JSON API is closed to new customers, and existing customers have until 1 January 2027 to move to an alternative. It gave 100 free queries a day and charged $5 per 1,000 queries after that. We cover that in more detail in Google Custom Search API alternatives.

The other Google names that show up in this search are not substitutes:

  • Google Photos APIs read and write a signed-in user’s own photo library. They do not search the web.
  • Cloud Vision analyses an image you give it, for example to label it. It does not search for images.

So if you want what you see on Google Images, as data, you need a SERP API.

What you need

  • A CrawlerData API key. New accounts get 50 free credits after verifying a work email, and every Google Images request costs 1 credit.
  • Python 3.9 or newer and the requests package (pip install requests).
  • The key in an environment variable:
export CRAWLERDATA_API_KEY="YOUR_API_KEY"

The Google Images API uses the same endpoint as every other CrawlerData API. Set endpoint to google-images:

import os
import requests

API_URL = "https://api.crawlerdata.com/v1/jobs"
HEADERS = {"Authorization": f"Bearer {os.environ['CRAWLERDATA_API_KEY']}"}


def google_images(query, country="us", language="en"):
    body = {
        "endpoint": "google-images",
        "params": {"query": query, "country": country, "language": language},
        "queue": "live",
    }
    resp = requests.post(API_URL, json=body, headers=HEADERS, timeout=180)
    resp.raise_for_status()
    data = resp.json()
    if data["job"]["status"] != "completed":
        raise RuntimeError(f"Image search failed: {data['job']['error']}")
    return data["result"]["images_results"]

The first result for golden retriever looked like this, trimmed:

{
  "position": 1,
  "title": "Golden Retriever: Pros, Cons & Diet Guide | Ollie",
  "source": "Ollie Blog",
  "link": "https://blog.ollie.com/breed-deets-golden-retriever/",
  "thumbnail": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSe1mLcW_M8xRI0J5...",
  "original_width": 2560,
  "original_height": 1707,
  "original": "https://blog.ollie.com/wp-content/uploads/250506_Livingroom_SHOT-10_0173_FR-scaled.jpg"
}
Field What it is
original The full-size image URL on the other site
original_width, original_height The size of that original, in pixels
thumbnail Google’s small copy of the image
link The page the image appears on
source, title The site name and the title Google shows

Keep original and link together. original is the file, link tells you where it came from.

One request, up to 100 images

Google Images shows more as you scroll, not as you click to a second page, so this endpoint returns one long list. In our test, golden retriever returned 100 images in a single request, for 1 credit.

That also means page only accepts 1. Asking for page 2 fails with a 400 and this message:

{
  "error": {
    "message": "Validation failed",
    "code": "VALIDATION_ERROR",
    "details": [{ "path": "params.page", "message": "Only page 1 is supported for this endpoint" }]
  }
}

To see different images, change the query. golden retriever puppy and golden retriever training give you different sets, each for 1 credit.

Keep only the images you can use

Many results are small. Each one carries its original size, so filtering takes a few lines. This function also removes duplicate image URLs and skips results with no size:

def big_images(query, min_width=1000, min_height=600, **kwargs):
    seen, rows = set(), []
    for r in google_images(query, **kwargs):
        w, h = r["original_width"], r["original_height"]
        if not r["original"] or r["original"] in seen:
            continue
        if w is None or h is None or w < min_width or h < min_height:
            continue
        seen.add(r["original"])
        rows.append({
            "title": r["title"],
            "source": r["source"],
            "page": r["link"],
            "image_url": r["original"],
            "width": w,
            "height": h,
        })
    return rows

For our query, 62 of the 100 results passed a 1000 by 600 minimum. The filter is yours to change: a minimum width for hero images, a square check for thumbnails, a ratio for banners.

Download the files

The original URLs point at other people’s servers, so expect some to fail. Our test run downloaded 9 of 10 images and one timed out. Treat each download as something that can fail, and check that what you got back is really an image:

import mimetypes
import re
from pathlib import Path


def download(rows, folder="images", limit=10):
    Path(folder).mkdir(exist_ok=True)
    saved = []
    for i, row in enumerate(rows[:limit], start=1):
        try:
            resp = requests.get(row["image_url"], timeout=30, headers={"User-Agent": "Mozilla/5.0"})
            resp.raise_for_status()
        except requests.RequestException as e:
            print("skip", row["image_url"][:60], type(e).__name__)
            continue
        ctype = resp.headers.get("Content-Type", "").split(";")[0]
        if not ctype.startswith("image/"):
            print("skip (not an image)", row["image_url"][:60], ctype)
            continue
        ext = mimetypes.guess_extension(ctype) or ".jpg"
        name = f"{i:02d}-{re.sub(r'[^a-z0-9]+', '-', row['title'].lower())[:40].strip('-')}{ext}"
        (Path(folder) / name).write_bytes(resp.content)
        saved.append({**row, "file": name})
    return saved

The file extension comes from the Content-Type the server sent, not from the URL, because image URLs often have no extension or the wrong one. If a server returns an HTML page instead of an image, the check skips it.

Then save a record of where each file came from, so you can trace it later:

import csv


def save_csv(rows, path="images.csv"):
    with open(path, "w", newline="", encoding="utf-8") as f:
        w = csv.DictWriter(f, fieldnames=list(rows[0]))
        w.writeheader()
        w.writerows(rows)


rows = big_images("golden retriever")
saved = download(rows, folder="images", limit=10)
save_csv(saved)

In our run this produced files such as a 2560 by 1707 image of about 534 KB and a 3000 by 3000 image of about 416 KB, with a CSV listing the source page for each.

Images belong to someone

A search result is a link to an image that another site owns. The API gives you the image URL, its size and the page it appears on. It does not give you a license, and being on Google Images does not make an image free to reuse. If you plan to publish, sell or train on what you download, check the source page’s terms first, and use the page column in your CSV to find it.

Country, language and cost

  • country takes one of 31 two-letter codes, such as us, gb, de or jp. language takes a two-letter code. The same query can return different images in different markets.
  • Every request is 1 credit on every queue, and a request that returns up to 100 images is still 1 credit. Starter is $1.00 per 1,000 requests and the largest pack $0.30 per 1,000, see pricing. Failed requests are not charged.
  • For many queries at once, submit jobs to the fast queue and collect them later instead of holding a connection open. The batch code in Get Google search results as JSON with Python works unchanged with endpoint set to google-images.

Next steps

You now have a function that returns up to 100 Google Images results per request, a size filter, a safe downloader and a CSV that records where each image came from. The Google Images API page lists every parameter with a full example response. If you also want the pages that rank for the same terms, the Google Search API returns them as JSON, and Google News results as JSON covers the news side.

Frequently asked questions

Is there an official Google Images API?
Not one you can sign up for today. Google's Custom Search JSON API could return image results, but it is closed to new customers and existing customers have until 1 January 2027 to move to something else. Google Photos APIs work on a user's own photo library, not on web image search.
How do I get Google Images results in Python?
POST to https://api.crawlerdata.com/v1/jobs with endpoint google-images, params with your query, and queue live. The result has an images_results list with the title, source, page link, thumbnail, original image URL and original width and height. This guide has the full code.
How many images do I get per request?
In our October 2026 test, one request for golden retriever returned 100 images for 1 credit. The endpoint supports page 1 only: asking for page 2 returns a validation error, because Google loads more images by scrolling rather than by page.
Does the API tell me an image's license?
No. Each result gives you the image URL, its size and the page it appeared on, not a license. Images belong to their owners, so check the source page's terms before you reuse one.
How do I get only large images?
Every result has original_width and original_height, so filter on them in your own code. In our test, 62 of 100 results were at least 1000 by 600 pixels.
How much does a Google Images search cost?
1 credit per request, which is $1.00 per 1,000 requests on the Starter pack and down to $0.30 per 1,000 on the largest. Because one request returns up to 100 images, the cost per image is a fraction of a cent. Failed requests are not charged.
  • Google Images API
  • Google image search
  • Python
  • Tutorial

Guides · 9 min read

Give your LLM agent fresh Google results

Add a Google search tool to an LLM agent: the tool definition, trimming results to fit the context window, citing sources and caching, in Python.