How to Integrate IndexNow API with Node.js — Step-by-Step Guide for Instant SEO Indexing
TL;DR
What is IndexNow?
IndexNow is an open protocol that allows websites to instantly notify search engines (like Bing, Yandex, etc.) whenever content is added, updated, or deleted. This helps search engines keep their index up to date.
Prerequisites
A Node.js project with
axios
installed.Access to your website’s root directory (for hosting the key).
A public-facing domain (e.g.,
https://www.example.com
).
Step 1: Generate Your IndexNow API Key
You need an API key to verify your domain.
- Generate a 32-character UTF-8 key. You can use an online generator or use this 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 API Key on Your Site
Create a .txt
file named with your key and put it in the root of your website.
Filename:
4262631fe57245bd9bd1cef01d1c3fa4.txt
Content inside file: The key itself (
4262631fe57245bd9bd1cef01d1c3fa4
)URL:
https://www.example.com/4262631fe57245bd9bd1cef01d1c3fa4.txt
Note: You can host the key in another directory, but then you'll need to use the keyLocation
parameter explicitly when submitting URLs.
Step 3: Submit URLs via Node.js Script
File Structure
├── config.js
├── indexnow.js <-- IndexNow logic
└── submit.js <-- Call and test submission
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');
}
if (urlList.length === 0) {
return { status: 'skipped', message: 'No URLs to submit' };
}
urlList = urlList.map((url) => siteUrl.replace(/\/$/, '') + "/" + url);
const siteDomain = getDomainFromUrl(siteUrl);
if (!siteDomain) throw new Error('Invalid site URL');
const data = {
host: siteDomain,
key: indexNowKey,
keyLocation: `${siteUrl.replace(/\/$/, '')}/${indexNowKey}.txt`,
urlList: urlList
};
const headers = {
'Content-Type': 'application/json',
'User-Agent': `${config.indexNow.agent}/${crypto.createHash('md5').update(siteUrl).digest('hex')}`,
'X-Source-Info': `https://${config.indexNow.source}/1.0/`
};
const response = await axios.post('https://api.indexnow.org/indexnow', data, { headers });
return {
status: 'success',
statusCode: response.status,
message: `Successfully submitted ${urlList.length} URLs`
};
} catch (error) {
const errorMessage = error.response ?
`HTTP ${error.response.status}: ${error.response.statusText}` : 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';
submitToIndexNow(siteUrl, apiKey, urls)
.then(result => {
console.log('📬 Submission Result:', result);
})
.catch(err => {
console.error('❌ Unexpected error:', err.message);
});
Step 4: Verify Submission in Bing Webmaster Tools
Add and verify your domain if not done already.
Use the URL inspection tool to verify submission status.