When you publish, change or delete a page, search engines normally find out the slow way: their crawler comes back on its own schedule, which can take days or weeks for a small site. IndexNow flips that around. Your site sends a short message saying “these URLs just changed”, and the participating search engines can crawl them straight away.
This guide covers the whole setup: what IndexNow is, which engines use it, how to make and host your key, how to submit one URL or thousands, how to automate it, what every response code means, and how to fix the usual problems. Every step works on any host or framework, and there are shortcuts for WordPress, Cloudflare and other platforms near the end.
{key}.txt containing that key to the root of your site, then send changed URLs to https://api.indexnow.org/indexnow. One submission reaches every participating search engine. Google is not one of them.What IndexNow is, and what it is not
IndexNow is an open protocol, launched in 2021 by Microsoft Bing and Yandex, for pushing change notifications to search engines instead of waiting for them to pull your pages. A notification is just a list of URLs plus a key that proves you control the site. When a search engine receives it, it can prioritise crawling those URLs.
Three things it is not:
- Not a guarantee of indexing. Bing says plainly that IndexNow makes search engines aware of changes but does not guarantee a page will be crawled or indexed. Thin, duplicate or blocked pages are still treated on their merits.
- Not a ranking factor. Being crawled sooner does not make a page rank higher. It only shortens the delay between your change and the search engine seeing it.
- Not a sitemap replacement. A sitemap lists every URL you want indexed; IndexNow announces what just changed. They work together. You can build one with the XML Sitemap Generator.
Which search engines support it
The participating engines publish their endpoints at indexnow.org. Submissions are shared: send your URLs to any one endpoint and they are passed on to all the others, so there is no need to submit to each engine separately.
| Search engine | Submission endpoint |
|---|---|
| Shared (any engine) | https://api.indexnow.org/indexnow |
| Microsoft Bing | https://www.bing.com/indexnow |
| Yandex | https://yandex.com/indexnow |
| Seznam.cz | https://search.seznam.cz/indexnow |
| Naver | https://searchadvisor.naver.com/indexnow |
| Yep | https://indexnow.yep.com/indexnow |
| Amazon (Amazonbot) | https://indexnow.amazonbot.amazon/indexnow |
| Internet Archive | https://web-static.archive.org/indexnow |
Bing’s results also feed several other search products (DuckDuckGo, Ecosia and Yahoo, among others, draw on Bing’s index), so the practical reach is wider than the list suggests.
Before you start
You need four things:
- A way to put a plain text file at the root of your site (FTP, your host’s file manager, your repository, or a CMS plugin that does it for you).
- The exact host you want to notify about.
www.example.comandexample.comare different hosts to IndexNow, and so are subdomains such asblog.example.com. Use the one your pages are actually served from (the one your canonical URLs use). - A list of the URLs that changed, as full absolute addresses (
https://www.example.com/page, not/page). - Optionally, a Bing Webmaster Tools account for the site, so you can see the submissions arrive.
Step 1: Generate a key
The key is a random string that ties your submissions to your site. The rules:
- 8 to 128 characters long.
- Only letters a–z and A–Z, digits 0–9 and the dash (
-). - The documentation describes it as hexadecimal, and a 32-character hexadecimal string such as
3f9c1a7e5b2d48f0a6c4e8b1d7f2a905is the safest choice: it satisfies every reading of the rules.
Any of these produces a suitable 32-character key:
# macOS, Linux, WSL or Git Bash
openssl rand -hex 16
# Python
python -c "import secrets; print(secrets.token_hex(16))"
# Node.js
node -e "console.log(require('crypto').randomBytes(16).toString('hex'))"
# Windows PowerShell (a GUID without dashes is 32 hex characters)
[guid]::NewGuid().ToString('N')
You can also take a version 4 UUID from the UUID Generator and remove the dashes. Keep one key per site; there is no benefit in making a new one for each submission.
Step 2: Host the key file
Search engines check that you own the site by fetching a file that contains your key. The standard place is the root of the host, with the key as the file name:
The file must contain only the key, as plain UTF-8 text. No HTML, no quotes and no other words. A trailing newline is harmless, but avoid saving it with a byte-order mark (some Windows editors add one; choose “UTF-8” rather than “UTF-8 with BOM”).
Check it from the command line before going further:
curl -i https://www.example.com/3f9c1a7e5b2d48f0a6c4e8b1d7f2a905.txt
You want to see a 200 status, ideally a Content-Type: text/plain header, and the key as the body. If you get a 404, the file is in the wrong folder; if you get a 301 or 302, the root URL you used redirects (for example from example.com to www.example.com), which means you are testing the wrong host.
Keeping the key file somewhere else
If you cannot write to the root, you can host the file elsewhere on the same host and tell the search engine where it is with the keyLocation parameter. The file can have any name, but its folder limits what it can verify: a key file at https://example.com/catalog/key.txt can only verify URLs that begin with https://example.com/catalog/. To cover a whole site, the root is still the right place.
Step 3: Submit one URL
The simplest submission is a GET request with the changed URL and your key as query parameters. The URL must be URL-encoded:
https://api.indexnow.org/indexnow?url=https%3A%2F%2Fwww.example.com%2Fnew-page&key=3f9c1a7e5b2d48f0a6c4e8b1d7f2a905
You can paste that into a browser address bar, or run it with cURL:
curl -i "https://api.indexnow.org/indexnow?url=https%3A%2F%2Fwww.example.com%2Fnew-page&key=3f9c1a7e5b2d48f0a6c4e8b1d7f2a905"
If your key file is not at the root, add &keyLocation= followed by the encoded address of the file. A response of 200 or 202 means it was received (the response codes are explained below).
Step 4: Submit many URLs at once
For more than one URL, send a POST request with a JSON body. One request can carry up to 10,000 URLs, and they must all belong to the host you name:
POST /indexnow HTTP/1.1
Host: api.indexnow.org
Content-Type: application/json; charset=utf-8
{
"host": "www.example.com",
"key": "3f9c1a7e5b2d48f0a6c4e8b1d7f2a905",
"keyLocation": "https://www.example.com/3f9c1a7e5b2d48f0a6c4e8b1d7f2a905.txt",
"urlList": [
"https://www.example.com/new-page",
"https://www.example.com/blog/updated-post",
"https://www.example.com/old-product"
]
}
keyLocation is optional when the key file is at the root, but including it does no harm and removes any doubt. The same request in a few languages follows. To turn the cURL version into another language, paste it into the cURL Converter.
cURL
curl -i -X POST "https://api.indexnow.org/indexnow" \
-H "Content-Type: application/json; charset=utf-8" \
--data '{"host":"www.example.com","key":"3f9c1a7e5b2d48f0a6c4e8b1d7f2a905","urlList":["https://www.example.com/new-page","https://www.example.com/blog/updated-post"]}'
PHP
<?php
function indexnow_submit(array $urls): int {
$payload = json_encode([
'host' => 'www.example.com',
'key' => '3f9c1a7e5b2d48f0a6c4e8b1d7f2a905',
'keyLocation' => 'https://www.example.com/3f9c1a7e5b2d48f0a6c4e8b1d7f2a905.txt',
'urlList' => array_values($urls),
], JSON_UNESCAPED_SLASHES);
$ch = curl_init('https://api.indexnow.org/indexnow');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
]);
curl_exec($ch);
$status = (int) curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
return $status; // 200 or 202 = received
}
// Send in batches of up to 10,000
foreach (array_chunk($changedUrls, 10000) as $batch) {
$status = indexnow_submit($batch);
}
Python
import requests
payload = {
"host": "www.example.com",
"key": "3f9c1a7e5b2d48f0a6c4e8b1d7f2a905",
"urlList": [
"https://www.example.com/new-page",
"https://www.example.com/blog/updated-post",
],
}
r = requests.post("https://api.indexnow.org/indexnow", json=payload, timeout=10)
print(r.status_code) # 200 or 202 = received
Node.js (18 or later)
const res = await fetch('https://api.indexnow.org/indexnow', {
method: 'POST',
headers: { 'Content-Type': 'application/json; charset=utf-8' },
body: JSON.stringify({
host: 'www.example.com',
key: '3f9c1a7e5b2d48f0a6c4e8b1d7f2a905',
urlList: ['https://www.example.com/new-page'],
}),
});
console.log(res.status); // 200 or 202 = received
Run these from your server, build script or CI job, not from a visitor’s browser. A script in a web page has no business holding your submission logic, and many sites’ Content-Security-Policy would block the request anyway.
Step 5: Automate it
IndexNow pays off when it runs by itself every time something changes. Submit a URL when a page is:
- Added: a new article, product or landing page.
- Updated: a meaningful change to the content, price, availability or title. Not a cache refresh or a tweak to a shared footer.
- Deleted: the page now returns 404 or 410. Submitting it tells engines to drop it.
- Redirected: submit the old URL (which now returns a 301 or 308) and, if it is new, the destination.
Common ways to wire it up:
- On save in your CMS or app: call your submit function after a page is published, updated or removed.
- On deploy, for static sites: compare the new sitemap with the previous one and submit every URL that was added, removed or whose
<lastmod>changed. This catches everything without touching individual templates. The Sitemap to IndexNow tool does this comparison for you and writes the submission script. - On a schedule: a cron job that collects the URLs changed since the last run and sends them in one POST. Fine for sites that change many pages a day.
Two rules keep you out of trouble. First, only submit URLs that really changed: the IndexNow FAQ asks you to wait at least 5 minutes between submissions of the same URL and not to resubmit the same pages many times a day. Second, do not bulk-submit your whole back catalogue when you first switch it on. Bing’s guidance is to submit URLs modified after you enable IndexNow; your sitemap already covers the rest.
Shortcuts for common platforms
- WordPress: install the official IndexNow plugin, or switch it on in Yoast SEO, Rank Math, All in One SEO or SEOPress, which all support it. These generate and host the key and submit pages on publish, update and delete. Only use one of them, or the same URLs will be sent twice.
- Cloudflare: turn on Crawler Hints in the dashboard. Cloudflare then sends IndexNow notifications based on what it sees changing in its cache, with no key file for you to manage.
- Hosted platforms: Shopify, Wix, GoDaddy, Duda and others submit automatically or offer a setting or app for it. Check your platform’s SEO settings before building anything yourself.
- Drupal, Joomla, PrestaShop, XenForo and similar: look for an IndexNow module or extension in the platform’s directory.
- Static site generators (Hugo, Jekyll, Eleventy, Astro and so on): use the deploy-time sitemap comparison above, run from your CI pipeline after the upload succeeds.
Reading the response codes
The response tells you whether the submission was accepted, not whether the pages will be indexed. Look up any other code in the HTTP Status Codes reference.
| Code | Meaning | What to do |
|---|---|---|
200 OK | The URLs were submitted successfully. | Nothing. |
202 Accepted | The URLs were received, but the key has not been validated yet. | Normal on the first submissions. Make sure the key file stays online. |
400 Bad Request | The request is malformed. | Check the JSON is valid, the Content-Type header is set, and the query parameters are encoded. |
403 Forbidden | The key is not valid: the key file was not found, or it was found but does not contain the key. | Fetch the key file yourself (Step 2) and compare its contents with the key you are sending. |
422 Unprocessable Entity | The URLs do not belong to the host, or the key does not match the schema. | Make every URL use exactly the host you sent, including www., and check the key’s length and characters. |
429 Too Many Requests | Too many submissions; the endpoint suspects spam. | Slow down, stop resubmitting unchanged URLs, and batch URLs into fewer, larger POST requests. |
Check that it is working
- The response: log the status code from every submission. A steady run of 200s (or 202s at first) means the protocol side is right.
- Bing Webmaster Tools: add and verify your site, then open the IndexNow section. It lists the URLs Bing has received through IndexNow, including ones that arrived via another engine’s endpoint, along with any errors.
- Your server logs: after a submission you will usually see Bingbot (and other participating crawlers) request those exact URLs soon afterwards. That is the clearest sign the notifications are being acted on.
Troubleshooting
- 403 even though the file exists. Open the key file URL in a private window. Common causes are a byte-order mark at the start of the file, HTML instead of plain text (some hosts wrap unknown files in an error page), the file being in a subfolder, or a bot-protection or firewall rule that challenges the search engine’s request. Allow the key file through any such rule.
- 422 on every request. Usually a host mismatch: you sent
"host": "example.com"but the URLs start withhttps://www.example.com/, or the other way round. The host and every URL must agree exactly. - The key file is cached with old content. If you changed the key, purge the file from your CDN cache. Search engines must see the new key at the new file name.
- Staging or preview sites. Never submit URLs from a staging host. If your CMS plugin runs on staging too, turn it off there.
- Pages submitted but never indexed. IndexNow only gets them crawled. Check that they are not blocked in
robots.txt(the robots.txt Generator has a URL tester), not markednoindex, and not near-duplicates of other pages. - Duplicate submissions. If a plugin and your own script both submit, every change is sent twice and can trigger 429 responses. Pick one.
Changing your key
You can rotate the key at any time. Upload the new key file, start sending the new key, then delete the old file. Search engines re-check ownership on later submissions, so nothing breaks. There is rarely a reason to rotate, because the key is public by design: it proves that whoever submits can also place a file on the site.
Setup checklist
- Generate a 32-character hexadecimal key.
- Upload
{key}.txt, containing only the key, to the root of the exact host you serve pages from. - Fetch it with
curl -i: expect200and the key as the body. - Submit one test URL with a GET request and check for
200or202. - Add a POST submission, in batches of up to 10,000, to your publish, update, delete and redirect events (or turn on a CMS plugin or Cloudflare Crawler Hints).
- Log the response codes and confirm submissions appear in Bing Webmaster Tools.
- Keep your XML sitemap up to date and submitted, including in Google Search Console, since Google does not use IndexNow.
Set up once, IndexNow needs no attention. The sitemap keeps the full list of your pages in front of search engines, and IndexNow tells them about each change as it happens.
Frequently asked questions
Does Google support IndexNow?
No. Google is not one of the participating search engines. IndexNow notifies Bing, Yandex, Seznam.cz, Naver, Yep, Amazon and the Internet Archive. For Google, keep a sitemap submitted in Search Console and use its URL Inspection tool for urgent pages.
Do I have to submit to every search engine separately?
No. A submission to any one participating endpoint, including the shared api.indexnow.org, is passed on to all the others. Sending the same URL to several endpoints just repeats the same notification.
How many URLs can I submit at once?
Up to 10,000 URLs in a single POST request, all on the same host. For more, split them into batches of 10,000 or fewer.
Does IndexNow replace my XML sitemap?
No. IndexNow tells search engines what just changed; a sitemap is the complete list of URLs you want indexed. Keep both: the sitemap for coverage, IndexNow for speed.
Will IndexNow get my pages indexed or ranked faster?
It gets them noticed faster, which usually means they are crawled sooner. It does not guarantee a page is indexed, and it has no effect on ranking. Search engines still decide what to crawl and index.
Should I submit pages I have deleted?
Yes. Submit the URL of a page you removed (it should return 404 or 410) or redirected (it should return a 301 or 308). That tells search engines to drop or update the old address instead of waiting to rediscover it.
Is my IndexNow key a secret?
Not really. It has to be publicly readable in the key file, so anyone can see it. Its job is to prove that whoever submits URLs for a host can also put a file on that host, not to protect anything.