How to Integrate IndexNow API with Node.js — Step-by-Step Guide for Instant SEO Indexing

IndexNow API IndexNow Node.js IndexNow integration guide Node.js SEO submit URLs to search engines instant indexing Node.js bing indexing api IndexNow API key setup search engine notification url submission API
Ankit Agarwal
Ankit Agarwal

Head of Marketing

 
July 24, 2025
6 min read

TL;DR

  • Integrate IndexNow in Node.js to speed up SEO indexing:
  • Generate a 32-character API key.
  • Host it as a .txt file on your domain.
  • Submit URLs via a POST request to the IndexNow API.
  • Verify using Bing Webmaster Tools.
  • Fast, simple, and improves search engine visibility

IndexNow is an open protocol that lets a website tell participating search engines the instant a page is added, updated, or deleted, instead of waiting for the next scheduled crawl. Microsoft Bing, Yandex, Seznam.cz, and the Internet Archive are current adopters; a single submission to the shared endpoint is automatically shared with every other participating engine (IndexNow documentation, retrieved 2026-09-18).

This guide walks through a working Node.js integration: generating a key, hosting it, and submitting URLs with a small reusable module, plus how to verify the submission actually landed.

Key Takeaways

  • IndexNow keys must be 8 to 128 hexadecimal characters, hosted as a plain-text file at your domain root or a custom keyLocation (IndexNow documentation, retrieved 2026-09-18).
  • A single POST to the shared endpoint (api.indexnow.org) fans out to every participating engine — you don't submit separately to each one.
  • IndexNow is a notification, not a ranking signal. It tells engines a URL changed; it doesn't influence how that page ranks.
  • Google does not participate in IndexNow as of this writing, so keep submitting an XML sitemap and using Search Console for Google indexing.
  • Batch submission supports up to 10,000 URLs per request, which matters if you publish or update pages at scale.

What Is IndexNow?

IndexNow answers one specific problem: search engines that only discover changes by re-crawling on their own schedule can take days to notice a new or updated page. IndexNow lets you push the notification instead of waiting to be pulled.

It complements, rather than replaces, an XML sitemap. A sitemap tells engines what exists; IndexNow tells them what just changed.

Prerequisites

  • A Node.js project with axios installed (npm install axios).
  • Write access to your website's root directory, since that's the default location for the key file.
  • A public-facing domain (for example, https://www.example.com).

Step 1: Generate Your IndexNow Key

You need a key to prove you control the domain you're submitting URLs for. The protocol requires 8 to 128 hexadecimal characters; a 32-character key is a common, safe default (IndexNow documentation, retrieved 2026-09-18).

Generate one with a short Node.js snippet:

const crypto = require('crypto');
const key = crypto.randomBytes(16).toString('hex');
console.log("Generated IndexNow Key:", key);

Example key: 4262631fe57245bd9bd1cef01d1c3fa4

Step 2: Host the Key on Your Site

Create a .txt file named after your key and place it in your website's root directory.

  • Filename: 4262631fe57245bd9bd1cef01d1c3fa4.txt
  • File content: just the key itself — 4262631fe57245bd9bd1cef01d1c3fa4
  • Resulting URL: https://www.example.com/4262631fe57245bd9bd1cef01d1c3fa4.txt

If you host the key file somewhere other than the root, pass its location explicitly with the keyLocation parameter when you submit URLs. Note that a custom keyLocation restricts submissions to URLs under that file's directory path (IndexNow documentation, retrieved 2026-09-18).

Step 3: Submit URLs via a Node.js Script

Project structure

/your-project
  ├── config.js
  ├── indexnow.js     <-- core submission logic
  └── submit.js       <-- run this to submit URLs

config.js

module.exports = {
  indexNow: {
    agent: 'my-custom-agent',
    source: 'my-website-source'
  }
};

indexnow.js — core logic

const crypto = require('crypto');
const axios = require('axios');
const config = require('./config');

function getDomainFromUrl(url) { try { const parsedUrl = new URL(url); return parsedUrl.hostname; } catch (e) { console.error('Invalid URL:', url); return null; } }

async function submitToIndexNow(siteUrl, indexNowKey, urlList) { try { if (!siteUrl || !indexNowKey || !urlList || !Array.isArray(urlList)) { throw new Error('Missing required parameters'); }

<span class="hljs-keyword">if</span> (urlList.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
  <span class="hljs-keyword">return</span> { <span class="hljs-attr">status</span>: <span class="hljs-string">&#x27;skipped&#x27;</span>, <span class="hljs-attr">message</span>: <span class="hljs-string">&#x27;No URLs to submit&#x27;</span> };
}

urlList = urlList.<span class="hljs-title function_">map</span>(<span class="hljs-function">(<span class="hljs-params">url</span>) =&gt;</span> siteUrl.<span class="hljs-title function_">replace</span>(<span class="hljs-regexp">/\/$/</span>, <span class="hljs-string">&#x27;&#x27;</span>) + <span class="hljs-string">&quot;/&quot;</span> + url);
<span class="hljs-keyword">const</span> siteDomain = <span class="hljs-title function_">getDomainFromUrl</span>(siteUrl);
<span class="hljs-keyword">if</span> (!siteDomain) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>(<span class="hljs-string">&#x27;Invalid site URL&#x27;</span>);

<span class="hljs-keyword">const</span> data = {
  <span class="hljs-attr">host</span>: siteDomain,
  <span class="hljs-attr">key</span>: indexNowKey,
  <span class="hljs-attr">keyLocation</span>: <span class="hljs-string">`<span class="hljs-subst">${siteUrl.replace(/\/$/, <span class="hljs-string">&#x27;&#x27;</span>)}</span>/<span class="hljs-subst">${indexNowKey}</span>.txt`</span>,
  <span class="hljs-attr">urlList</span>: urlList
};

<span class="hljs-keyword">const</span> headers = {
  <span class="hljs-string">&#x27;Content-Type&#x27;</span>: <span class="hljs-string">&#x27;application/json&#x27;</span>,
  <span class="hljs-string">&#x27;User-Agent&#x27;</span>: <span class="hljs-string">`<span class="hljs-subst">${config.indexNow.agent}</span>/<span class="hljs-subst">${crypto.createHash(<span class="hljs-string">&#x27;md5&#x27;</span>).update(siteUrl).digest(<span class="hljs-string">&#x27;hex&#x27;</span>)}</span>`</span>,
  <span class="hljs-string">&#x27;X-Source-Info&#x27;</span>: <span class="hljs-string">`https://<span class="hljs-subst">${config.indexNow.source}</span>/1.0/`</span>
};

<span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.<span class="hljs-title function_">post</span>(<span class="hljs-string">&#x27;https://api.indexnow.org/indexnow&#x27;</span>, data, { headers });

<span class="hljs-keyword">return</span> {
  <span class="hljs-attr">status</span>: <span class="hljs-string">&#x27;success&#x27;</span>,
  <span class="hljs-attr">statusCode</span>: response.<span class="hljs-property">status</span>,
  <span class="hljs-attr">message</span>: <span class="hljs-string">`Successfully submitted <span class="hljs-subst">${urlList.length}</span> URLs`</span>
};

} catch (error) { const errorMessage = error.response ? HTTP <span class="hljs-subst">${error.response.status}</span>: <span class="hljs-subst">${error.response.statusText}</span> : error.message; return { status: 'error', error: errorMessage, message: 'Failed to submit URLs' }; } }

module.exports = { submitToIndexNow, getDomainFromUrl };

submit.js — run the submission

const { submitToIndexNow } = require('./indexnow');

const apiKey = '4262631fe57245bd9bd1cef01d1c3fa4'; const urls = [ 'blog/passwordless-authentication-guide', 'blog/resistant-cryptography-migration' ]; const siteUrl = 'https://www.example.com&#x27;;

submitToIndexNow(siteUrl, apiKey, urls) .then(result => { console.log('Submission result:', result); }) .catch(err => { console.error('Unexpected error:', err.message); });

A batch request like this supports up to 10,000 URLs per submission, which is the relevant limit if you're publishing pages programmatically rather than one at a time (IndexNow documentation, retrieved 2026-09-18).

Step 4: Verify the Submission

After running the script, confirm the submission actually registered.

  1. Go to Bing Webmaster Tools' IndexNow page.
  2. Add and verify your domain if you haven't already.
  3. Use the URL Inspection tool there to check submission status.

A successful call returns HTTP 200 (accepted) or 202 (accepted, pending key validation). A 400 means a malformed request, 403 means the key failed validation, 422 means the URLs don't match the submitted host, and 429 means you've hit the rate limit (IndexNow documentation, retrieved 2026-09-18).

Why This Matters Beyond Traditional SEO

Fast indexing isn't just a traditional-search concern. AI answer engines like Perplexity and Google's AI Overviews rely on retrieval systems that pull from a search index too, so a page an engine hasn't crawled yet can't be cited in an AI-generated answer either. Getting new or updated pages indexed quickly is table stakes for both goals, which is one reason a platform built for AI search visibility, like GrackerAI, treats fast indexing as infrastructure rather than an afterthought when it publishes programmatic content at scale.

If you're publishing or updating pages programmatically, pair this with the rest of your technical SEO stack: our comprehensive technical SEO audit checklist covers crawlability and indexability end to end, and schema automation at scale covers the structured-data side of publishing thousands of pages without doing it by hand.

How This Guide Was Sourced

This guide is written by GrackerAI's research and content team, which builds AI-optimized content production and AI search visibility tracking for cybersecurity and B2B SaaS vendors — disclosed here since the guide also links to our own platform. Protocol details (key format, endpoints, response codes, participating engines) are drawn from the official IndexNow documentation and participating search engines list, both retrieved 2026-09-18. The protocol and its adopter list can change; pin your reading to the retrieval date above and re-check the official documentation before relying on specifics in production. No GrackerAI telemetry is used in this guide.

Frequently Asked Questions

Does IndexNow guarantee faster rankings?

No. IndexNow is a notification protocol, not a ranking signal. It tells participating engines a URL changed so they can choose to re-crawl it sooner; it has no direct effect on where that page ranks once indexed.

Do I need to submit to Bing, Yandex, and every other engine separately?

No. A single submission to the shared endpoint (api.indexnow.org) is automatically shared with every other participating engine, per the protocol's design (IndexNow documentation, retrieved 2026-09-18).

Does Google support IndexNow?

Google is not among the engines listed in IndexNow's official participant registry as of this writing. Continue submitting an XML sitemap and using Google Search Console's URL Inspection tool for Google indexing.

What happens if my key file returns a 404?

The submission will fail key validation. Double-check the key file is publicly accessible at the exact URL your submission's keyLocation (or the domain root) points to, with no authentication or redirect in front of it.

How many URLs can I submit in one request?

Up to 10,000 URLs per batch submission, which is the relevant number if you're publishing programmatically rather than one page at a time (IndexNow documentation, retrieved 2026-09-18).

Can I rotate or revoke my IndexNow key?

Yes. Generate a new key, host its .txt file, and start submitting with it. There's no separate revocation step; an old key simply stops being used once you stop referencing it in submissions.

Ankit Agarwal
Ankit Agarwal

Head of Marketing

 

Ankit Agarwal is a growth and content strategy professional specializing in SEO-driven and AI-discoverable content for B2B SaaS and cybersecurity companies. He focuses on building editorial and programmatic content systems that help brands rank for high-intent search queries and appear in AI-generated answers. At Gracker, his work combines SEO fundamentals with AEO, GEO, and AI visibility principles to support long-term authority, trust, and organic growth in technical markets.

Related Articles

The Data Layer Behind AI Search Visibility
AI search visibility

The Data Layer Behind AI Search Visibility

Discover how the data layer influences AI search visibility. Learn actionable strategies to optimize your content for LLMs and generative search engines today.

By Vijay Shekhawat September 24, 2026 8 min read
common.read_full_article
The Role of Backlinks in Editorial and Programmatic SEO for SaaS
editorial SEO

The Role of Backlinks in Editorial and Programmatic SEO for SaaS

Learn how backlinks power editorial and programmatic SEO for SaaS, boosting authority, rankings, and scalable content performance for long-term growth.

By Govind Kumar September 23, 2026 7 min read
common.read_full_article
Cybersecurity Marketing Agencies: The Complete Guide to Choosing, Evaluating, and Working With One
cybersecurity marketing agency

Cybersecurity Marketing Agencies: The Complete Guide to Choosing, Evaluating, and Working With One

A pillar guide to hiring, evaluating, and working with a cybersecurity marketing agency, including how AI answer engines are changing how buyers vet one.

By Ankit Agarwal September 21, 2026 13 min read
common.read_full_article
10 Best Cybersecurity Marketing Agencies in 2026
cybersecurity marketing agency

10 Best Cybersecurity Marketing Agencies in 2026

10 verified full-service cybersecurity marketing agencies for 2026, compared by focus and differentiator, plus why AI search visibility belongs on your agency checklist.

By Ankit Agarwal September 21, 2026 15 min read
common.read_full_article