Google Indexing API with Node.js: Send One Notification

Use GoogleAuth and googleapis to send an eligible URL_UPDATED notification, inspect failures, and distinguish notification metadata from indexing status.
Harlan WiltonHarlan Wilton5 min read Published Updated

Use Google's googleapis client to send one URL_UPDATED notification from a server-side Node.js script. The example uses Node.js 24 and googleapis 181.0.0.

Before running it against Google, complete the service-account setup, including delegated property ownership and approval. Google supports only eligible JobPosting pages, or BroadcastEvent embedded in VideoObject; see Google's quickstart.

Install and run

Keep the service-account JSON key outside Git and public directories. In a new local directory:

npm init -y
npm install googleapis@181.0.0
export GOOGLE_APPLICATION_CREDENTIALS="/absolute/path/to/service-account.json"

Save the following as notify.mjs:

import { google } from 'googleapis'

const url = process.argv[2]
if (!url) {
  throw new Error('Pass one eligible URL: node notify.mjs URL')
}

const auth = new google.auth.GoogleAuth({
  scopes: ['https://www.googleapis.com/auth/indexing'],
})
const indexing = google.indexing({ version: 'v3', auth })

await indexing.urlNotifications.publish({
  requestBody: { url, type: 'URL_UPDATED' },
}, { retry: false }).then(({ data }) => {
  console.log(JSON.stringify({ status: 'notification-accepted', url, metadata: data }))
}).catch((error) => {
  const details = error.response?.data?.error
  console.error(JSON.stringify({
    status: 'request-failed',
    url,
    httpStatus: error.response?.status,
    reasons: details?.errors?.map(item => item.reason),
    message: details?.message ?? error.message,
  }))
  process.exitCode = 1
})
node notify.mjs 'https://example.com/jobs/42'

The library reads the credential file through GOOGLE_APPLICATION_CREDENTIALS. GoogleAuth supplies the scoped authentication to the Indexing API client. The current Google client and authentication documentation describe this pattern.

What the output means

A successful response produces notification-accepted. That label reports receipt only. It says nothing about a crawl or an indexed page, so if you store the result, keep the receipt apart from indexing status.

Google Search timelines explains why an accepted notification does not set an indexing deadline.

The failure path prints the HTTP status and, when Google returns them, its structured reasons. It also sets a nonzero exit code so a calling job can detect the failure. This small example disables automatic retries: find the cause first, then decide what to retry.

A 429 does not identify the exhausted limit by itself, and a 403 is not always an ownership error. Compare the reason and message with Google's error reference and the quota guide.

Read notification metadata separately

In a script with the same indexing client and url, you can read the notification record:

const { data } = await indexing.urlNotifications.getMetadata({ url })
console.log(data)

The snippet depends on that client and url, so it will not run on its own. Metadata describes the last notification Google received for that URL. It does not establish index status. Google's usage guide documents the distinction.

For index information, use the separate URL Inspection API and its Search Console authorization scope. For a one-off check without code, the Google index checker runs a site: search for a single URL and reports whether it returns a result.

When you have several URLs

For a list of eligible URLs, start with sequential submission. It is easier to inspect each result before adding multipart batching or a shared queue.

Verification here used Node.js 24.18.0 and the actual installed client with a mocked credential provider and intercepted HTTP transport. It checked request construction and success/failure output. It did not establish valid credentials, property ownership, or a live indexing outcome.