Skip to content
TurboIndex

Google Indexing API Guide: Setup, Quotas, Limits and Risks

What the Google Indexing API does, who it is officially for, the 200 per day quota, service account setup, a Node.js example and 403 and 429 errors explained.

September 1, 20268 min read

The Google Indexing API lets a site owner tell Google directly that a URL was added, updated or removed, so Google can schedule a fresh crawl. Officially it is only for pages with JobPosting structured data or BroadcastEvent embedded in a VideoObject. The default quota is 200 publish requests per day per Google Cloud project, the calling service account must be an Owner of the Search Console property, and a successful call is a crawl request, never an indexing guarantee.

Most guides skip the second sentence. This one does not, because whether you should use the API at all depends on it.

What the API does and does not do

There are only two real operations:

Operation Request Purpose
Publish POST https://indexing.googleapis.com/v3/urlNotifications:publish Notify Google that a URL was updated (URL_UPDATED) or removed (URL_DELETED)
Get metadata GET https://indexing.googleapis.com/v3/urlNotifications/metadata?url=... See the last notifications you sent for a URL

What people often get wrong:

  • A 200 response means "notification received". It does not mean crawled, and it certainly does not mean indexed.
  • getMetadata does not report index status. It only echoes your own notifications and returns 404 if you never sent one for that URL. To see whether a page is indexed, you need the URL Inspection tool or the URL Inspection API, as described in how to check if a page is indexed.
  • URL_DELETED is for pages that are really gone. The page should return 404 or 410, or carry a noindex, before you send it.

Who it is officially for

Google's documentation is explicit: the Indexing API can only be used to crawl pages with either JobPosting or BroadcastEvent embedded in a VideoObject. These are short-lived pages where hours matter. A job ad that is filled, or a livestream that starts tonight, is useless if it is crawled next week.

In September 2024 Google added further wording to the docs:

  • All submissions go through spam detection.
  • Attempts to abuse the API, "including the use of multiple accounts or other means to exceed usage quotas", may result in access being revoked.
  • Google's spam policies apply to content submitted through the API.
  • The default 200 per day quota is described as being for onboarding and submission testing, with additional approval required beyond that.

The honest position on other content types

The API accepts any URL on a property you own. It does not check for job or broadcast markup at submission time. Many site owners and tools use it for blog posts, products and landing pages, and commonly report that those URLs get crawled quickly.

Here is what you should weigh before doing the same:

  • It is unsupported. Google's John Mueller has said repeatedly that the API supports a very limited set of use cases and that people should stick to the documented ones. Google can stop honouring other submissions at any time without notice.
  • A crawl is not an index entry. If a page is thin or duplicated, the API gets it crawled sooner and rejected sooner. It does not fix Crawled - currently not indexed.
  • Quota evasion is the clearly risky part. Rotating many Google Cloud projects or accounts to push thousands of URLs per day is exactly what the abuse wording describes. The exposure is loss of API access, and your site being treated as a spam source.
  • Quota increases are hard to get. Requests go through a form linked from the quota page. Third-party reports indicate approvals have been rare, particularly for sites that are not job boards or livestream platforms.

My view: for job and livestream pages, use it without hesitation. For other content, staying within the default quota on a single project is a low-volume, best-effort crawl hint that you should be ready to lose. It is no substitute for sitemaps, internal links and content Google wants to keep. TurboIndex works this way by default: one project per site, the standard 200 per day, and index status verified separately through the URL Inspection API so you see what actually happened.

Quotas

Quota Default
Publish requests (URL_UPDATED plus URL_DELETED) 200 per day per project
Metadata requests 180 per minute per project
All requests 380 per minute per project

The daily counter resets at midnight Pacific Time. The API is free. Google notes that quota may increase or decrease based on document quality. Multiple service accounts inside one project share the same 200. To estimate how long your site would take at this rate, use the indexing time calculator.

Setup

1. Create a project and enable the API

  1. Open the Google Cloud Console and create a project (or pick an existing one).
  2. Go to APIs & Services > Library, search for "Web Search Indexing API" and click Enable.

2. Create a service account and key

  1. Go to IAM & Admin > Service Accounts > Create service account. No project roles are needed.
  2. Open the account, go to Keys > Add key > Create new key > JSON and download the file.
  3. Note the client_email. It looks like [email protected].

The JSON file is a full credential. Keep it out of git, store it as a secret and rotate it if it leaks. If your Google Cloud organisation enforces the policy that disables service account key creation, an admin has to allow it for the project first.

3. Add the service account as an Owner in Search Console

  1. In Search Console select the property, then Settings > Users and permissions.
  2. Click Add user, paste the service account email, and set Permission to Owner.

Both Domain properties and URL-prefix properties work. With a URL-prefix property the submitted URL must fall under that exact prefix. This is the step where most setups fail: adding the account as "Full" produces a 403 on every call.

4. Send a notification (Node.js)

// npm install google-auth-library
import { readFileSync } from "node:fs";
import { JWT } from "google-auth-library";

const key = JSON.parse(readFileSync("./service-account.json", "utf8"));

const client = new JWT({
  email: key.client_email,
  key: key.private_key,
  scopes: ["https://www.googleapis.com/auth/indexing"],
});

async function notify(url, type = "URL_UPDATED") {
  try {
    const res = await client.request({
      url: "https://indexing.googleapis.com/v3/urlNotifications:publish",
      method: "POST",
      data: { url, type },
    });
    return res.data.urlNotificationMetadata;
  } catch (err) {
    const status = err.response?.status;
    const message = err.response?.data?.error?.message;
    if (status === 429) {
      // Daily quota used up: stop until midnight Pacific Time.
      throw new Error("Quota exhausted: " + message);
    }
    if (status === 403) {
      // Ownership or API not enabled: retrying will not help.
      throw new Error("Permission problem: " + message);
    }
    throw err;
  }
}

console.log(await notify("https://www.example.com/jobs/frontend-developer"));

The library signs a JWT with your private key, exchanges it for a one-hour access token and refreshes it automatically. If you load the private key from an environment variable, keep the \n line breaks intact or signing will fail.

5. Batch requests (optional)

You can combine up to 100 calls in one multipart request to https://indexing.googleapis.com/batch. Each part carries its own status in the response. Quota is still counted per URL, so a batch of 100 costs 100 publish requests.

Error codes and what to do

HTTP Message (typical) Cause Action
400 "Missing attribute. 'url' attribute is required." or invalid type Malformed body Send JSON with url and type, and Content-Type: application/json
401 Invalid or expired credentials Bad token, clock skew, deleted key Mint a new token, check server time
403 "Permission denied. Failed to verify the URL ownership." Service account is not an Owner of a property covering the URL Add it as Owner, check protocol and host match
403 Project is not configured to access this API Indexing API not enabled in the project that owns the key Enable it under APIs & Services
404 Not found (on getMetadata) You never sent a notification for this URL Nothing, this is informational
429 "Insufficient tokens for quota..." Per-minute or per-day quota hit Per minute: back off and retry. Per day: stop until midnight Pacific
5xx Server error Temporary problem at Google Retry with exponential backoff

Two debugging tips for the ownership 403. First, check you are adding the email from the same JSON key you are signing with, since people often have several projects. Second, call the Search Console API sites.list method as the service account (scope webmasters.readonly). If the property does not come back with permissionLevel: "siteOwner", the Indexing API will refuse you too.

Good practice

  • Notify only on real change. New page, meaningful update, or removal. Do not resubmit unchanged URLs on a schedule.
  • Check before you submit. Make sure the URL returns 200, has no noindex and is canonical. The indexability checker does this per URL. Spending quota on redirects and noindexed pages is waste.
  • Spend quota where it helps. Skip URLs that are already indexed. A URL that has impressions in the Performance report is provably indexed.
  • Keep a log of URL, type, time and response, so you never need getMetadata to know what you sent.
  • Verify outcomes. Inspect a sample a few days later. If pages are crawled and not indexed, the bottleneck is content, and more notifications will not help.
  • Keep the basics. Google recommends sitemaps for broad coverage even when you use the API.

What not to do

  • Do not create dozens of Cloud projects to multiply the quota. That is the behaviour Google's abuse notice names.
  • Do not send URL_DELETED for pages that still exist just to "refresh" them.
  • Do not treat the API as a fix for pages Google has already declined to index.
  • Do not hand your service account key to a tool you do not trust. The key gives whoever holds it Owner-level API access to your Search Console property.

Alternatives that are fully supported

  • XML sitemaps with accurate lastmod, submitted in Search Console. See the XML sitemap guide.
  • Request indexing in the URL Inspection tool for individual pages.
  • IndexNow for Bing, Yandex, Naver, Seznam and others. Google does not participate, but it takes a minute to set up and you can send URLs with the IndexNow submitter. More in the IndexNow guide.
  • Internal links from pages Google already crawls often.

If you run a job board or a livestream site, the Indexing API is the right tool and worth the hour of setup. For everything else, treat it as an optional extra on top of the fundamentals, with clear eyes about what Google has and has not promised.

Frequently asked questions

Can I use the Google Indexing API for any website?
Officially no. Google's documentation says the Indexing API can only be used for pages with JobPosting structured data or BroadcastEvent embedded in a VideoObject. The API technically accepts other URLs and many people use it that way, but that use is unsupported and Google can ignore it or revoke access.
What is the Indexing API quota?
The default is 200 publish requests per day per Google Cloud project, counting URL_UPDATED and URL_DELETED together, plus 180 metadata requests per minute and 380 total requests per minute. The daily quota resets at midnight Pacific Time. Google describes the 200 as a quota for onboarding and testing.
Does the Indexing API guarantee that my page gets indexed?
No. A successful response only means Google received the notification and will schedule a crawl. Whether the page is then indexed depends on the same quality and duplication checks as any other page. Check the actual result with the URL Inspection tool or API.
Why do I get 403 Permission denied. Failed to verify the URL ownership?
The service account that signed the request is not an Owner of a Search Console property that contains the URL. Add the service account email under Settings, Users and permissions with the Owner permission. Full user is not enough. Also check that the URL matches the property's protocol and host.
Is batching a way around the daily quota?
No. A batch request can combine up to 100 calls into one HTTP request, but each URL in the batch still counts as one publish request against the daily quota. Batching only saves HTTP round trips.

Keep reading