How to Submit to IndexNow?
A recipe-style guide to telling search engines about your fresh content the moment you publish it — no waiting for crawlers to find you.
Ingredients
- A website you control — any domain where you can upload a text file
- A random API key — 8 to 128 hex characters
- A way to make HTTP requests —
curl, Python, a CI pipeline, or your agent - A list of URLs you want indexed
IndexNow is an open ping protocol co-developed by Microsoft and Yandex. Instead of waiting days or weeks for crawlers to rediscover your pages, you push a notification the moment content changes — and participating search engines pick it up within minutes. Bing, Yandex, Seznam, Naver, and Yep all honour it. Google does not participate directly, but a single submission is broadcast to every IndexNow-enabled engine, so you cover a lot of ground with one call.
1 Generate a key
Your key is a random string between 8 and 128 characters long, using letters, digits, and dashes. Any UUID or hex blob works. Generate one with:
openssl rand -hex 16
# → 7a4f1e9b8c2d3f5a6b1c9d0e2f4a6b8c
Save this value somewhere safe — it is the secret that proves you own the domain. Anyone who knows your key can submit URLs on your behalf.
2 Host the key file
Create a plain-text file whose name is your key, with .txt
on the end. The file’s contents must also be the key — nothing
else. Place it at the root of your site so it is reachable at:
https://yourdomain.com/7a4f1e9b8c2d3f5a6b1c9d0e2f4a6b8c.txt
This is how search engines verify that whoever is submitting URLs
actually controls the domain. You can also host the key file at a
subpath if you prefer — just remember the full URL, because you
will pass it as keyLocation in your requests.
curl https://yourdomain.com/<key>.txt should return
exactly your key and a 200 status. A 403 or
404 will cause all your submissions to be rejected silently.
3 Submit a single URL
The simplest submission is an HTTP GET to any IndexNow
endpoint. Use this when you just published a single page and want it
indexed now:
curl "https://api.indexnow.org/indexnow\
?url=https://yourdomain.com/new-article\
&key=7a4f1e9b8c2d3f5a6b1c9d0e2f4a6b8c"
A 200 OK means the submission was accepted. You can swap
api.indexnow.org for www.bing.com/indexnow or
yandex.com/indexnow — it does not matter which endpoint
you hit, because all of them share submissions with the other
participating engines.
4 Submit a batch of URLs
For sitemaps, rebuilds, or bulk updates, send a POST with a
JSON body. You can include up to 10,000 URLs in a single request:
curl -X POST "https://api.indexnow.org/indexnow" \
-H "Content-Type: application/json; charset=utf-8" \
-d '{
"host": "yourdomain.com",
"key": "7a4f1e9b8c2d3f5a6b1c9d0e2f4a6b8c",
"keyLocation": "https://yourdomain.com/7a4f1e9b8c2d3f5a6b1c9d0e2f4a6b8c.txt",
"urlList": [
"https://yourdomain.com/",
"https://yourdomain.com/how-to-claw",
"https://yourdomain.com/how-to-indexnow"
]
}'
Same idea, more URLs per call. Python version for a deploy script:
import requests
KEY = "7a4f1e9b8c2d3f5a6b1c9d0e2f4a6b8c"
HOST = "yourdomain.com"
payload = {
"host": HOST,
"key": KEY,
"keyLocation": f"https://{HOST}/{KEY}.txt",
"urlList": [
f"https://{HOST}/",
f"https://{HOST}/how-to-claw",
f"https://{HOST}/how-to-indexnow",
],
}
r = requests.post(
"https://api.indexnow.org/indexnow",
json=payload,
headers={"Content-Type": "application/json; charset=utf-8"},
timeout=10,
)
print(r.status_code, r.text)
5 Read the response codes
IndexNow returns a small set of status codes. Memorise them:
200— accepted. You are done.202— accepted but key not yet verified. The engine will fetch your key file.400— bad request. Check your JSON shape and URL encoding.403— key invalid. The key file atkeyLocationdid not match.422— URLs don’t belong tohost, or the key violates the format rules.429— rate limited. Back off and retry later.
6 Wire it into your deploy
The best time to submit is right after a successful deploy. For a static site, add a final step to your CI pipeline that posts the changed URLs. A GitHub Actions snippet that fits cleanly at the end of the deploy workflow:
- name: Notify IndexNow
run: |
curl -X POST "https://api.indexnow.org/indexnow" \
-H "Content-Type: application/json; charset=utf-8" \
-d '{
"host": "yourdomain.com",
"key": "${{ secrets.INDEXNOW_KEY }}",
"keyLocation": "https://yourdomain.com/${{ secrets.INDEXNOW_KEY }}.txt",
"urlList": [
"https://yourdomain.com/",
"https://yourdomain.com/how-to-claw"
]
}'
What you end up with
A one-line step at the end of your deploy that tells Bing, Yandex, and every other participating search engine about your new and updated pages — typically indexed within minutes instead of days. No dashboards to check, no sitemaps to wait on.