Google index checker API: what replaces Custom Search JSON API after January 1, 2027

Many in-house index checkers are built on one trick: send site:example.com/page to the Google Custom Search JSON API and treat a non-empty result as “indexed”. That trick has an end date. Google is retiring the Custom Search JSON API on January 1, 2027, has already closed it to new customers, and points existing users to a partner-only Web Search Service API with no published pricing or quota (Search Engine Watch, Google docs).

This page covers what the shutdown changes for index checking specifically, and how to replace the call with a purpose-built endpoint.

What you lose

Requirements for a replacement

  1. Bulk input — thousands of URLs per request, not one query per call.
  2. A verdict per URL (indexed / not indexed), not a list of search results to parse.
  3. A predictable price per URL, without a daily cap that stretches a job across days.
  4. Auth with a static key, so the check fits into a cron job or CI step.

The SpeedyIndex checker API

SpeedyIndex exposes its bulk Google index check as a REST API. The relevant calls, from the official documentation at en.speedyindex.com/api.php:

Step Call Notes
Create a check task POST https://app.speedyindex.com/v2/task/google/checker/create body {"title": "...", "urls": [...]}, up to 10,000 URLs per request
Poll status POST /v2/task/google/checker/status body {"task_id": "..."}
Download results POST /v2/task/google/checker/fullreport returns indexed_links and unindexed_links arrays

Authentication is a single header: Authorization: <API key>. The key is issued in the app dashboard or the Telegram bot. The checker uses its own balance, separate from indexing tokens; current per-URL pricing is on the Google index checker page.

Minimal migration script

The script below replaces a typical site:-through-CSE loop. It reads URLs from a file, creates one task per 10,000 URLs, waits for completion, and writes two files: indexed.txt and unindexed.txt. Full file: scripts/speedyindex_check.py.

import os, sys, time, requests

API = "https://app.speedyindex.com"
KEY = os.environ["SPEEDYINDEX_API_KEY"]
H = {"Authorization": KEY, "Content-Type": "application/json"}

def create(urls, title):
    r = requests.post(f"{API}/v2/task/google/checker/create",
                      json={"title": title, "urls": urls}, headers=H, timeout=60)
    r.raise_for_status()
    return r.json()["task_id"]

def report(task_id):
    r = requests.post(f"{API}/v2/task/google/checker/fullreport",
                      json={"task_id": task_id}, headers=H, timeout=60)
    r.raise_for_status()
    return r.json()

Expected console output when the job finishes:

task 6609d0...: 4,812 indexed / 188 not indexed
wrote indexed.txt, unindexed.txt

Limitations