GPTBot IP Ranges 2026: JSON List and a Log Check
OpenAI lists 18 GPTBot IPv4 prefixes in gptbot.json (read 1 Nov 2026). Download it and run a Python check that flags log lines outside the range.
- gptbot
- openai
- ip-ranges
- log-analysis
- bot-verification
OpenAI publishes the GPTBot IP ranges at https://openai.com/gptbot.json: 18 IPv4 prefixes, file created 22 September 2026, as read on 1 November 2026. Test each log line's client IP against those prefixes with Python's ipaddress module, and treat a GPTBot user agent from an address outside the file as unverified.
As of 1 November 2026.
A user agent is a string any client can send. If your firewall, rate limiter or crawl report trusts the word "GPTBot" alone, a stranger can borrow OpenAI's standing with one header. So where is the list, and what does a match prove?
Where are the GPTBot IP ranges published? Method and numbers
OpenAI documents a separate list of crawler IP addresses for GPTBot, OAI-SearchBot, ChatGPT-User and OAI-AdsBot. Each is a JSON file with a creationTime and a prefixes array of CIDR blocks. OpenAI's crawler documentation (checked 1 November 2026) prints the URL under each bot as "Published IP addresses".
Method. We fetched the four files from openai.com on 30 October 2026 and counted entries with Python's standard library. We fetched gptbot.json a second time that day and got the same creationTime and 18 prefixes. Counts are CIDR entries, not addresses. This is a one-day snapshot, and the lists change.
| Bot | JSON file | Prefixes | Families | Prefix lengths | creationTime |
|---|---|---|---|---|---|
| GPTBot | https://openai.com/gptbot.json | 18 | IPv4 only | four /24, thirteen /25, one /28 | 2026-09-22T02:00:07.000000 |
| OAI-SearchBot | https://openai.com/searchbot.json | 39 | IPv4 only | two /24, thirteen /25, twenty-four /28 | 2026-01-02T11:00:00.000000 |
| ChatGPT-User | https://openai.com/chatgpt-user.json | 235 | IPv4 only | one /16, 234 /28 | 2026-10-27T18:04:58.004307 |
| OAI-AdsBot | https://openai.com/adsbot.json | 2 | IPv4 only | two /25 | 2026-05-12T03:00:00.000000 |
All four files use the key ipv4Prefix for every entry. None held an IPv6 prefix on the check date.
You have the file. How do you test a log against it?
How do I match a log line against the list?
The match is a CIDR membership test. The script parses the client IP and checks whether it falls inside any published prefix. Python's ipaddress.ip_network and the in operator do this with no extra package, and the same code handles IPv6 addresses if a list ever carries them.
This script downloads gptbot.json and reads a combined-format log, where the client IP is the first field and the user agent is the last quoted field. Adapt the regex if your format differs.
import ipaddress
import json
import re
import sys
import urllib.request
URL = "https://openai.com/gptbot.json"
def load_networks(path_or_url):
if path_or_url.startswith("http"):
with urllib.request.urlopen(path_or_url, timeout=20) as r:
data = json.load(r)
else:
with open(path_or_url) as f:
data = json.load(f)
nets = [ipaddress.ip_network(p.get("ipv4Prefix") or p.get("ipv6Prefix"))
for p in data["prefixes"]]
return data["creationTime"], nets
# combined log format: client IP first, user agent is the last quoted field
LINE = re.compile(r'^(\S+) .*"([^"]*)"$')
creation, nets = load_networks(sys.argv[2] if len(sys.argv) > 2 else URL)
print(f"list creationTime={creation} prefixes={len(nets)}")
for line in open(sys.argv[1]):
m = LINE.match(line.rstrip("\n"))
if not m:
continue
ip, ua = m.groups()
if "GPTBot" not in ua:
continue
addr = ipaddress.ip_address(ip)
inside = any(addr in n for n in nets)
print(f"{ip:<16} {'INSIDE ' if inside else 'OUTSIDE'} {ua}")
The test log has six lines. Five carry the user agent from OpenAI's documentation, GPTBot/1.4, and one is a browser. The addresses are documentation ranges plus the public resolver 8.8.8.8, so none is real OpenAI traffic. Here is the first line:
203.0.113.10 - - [30/Oct/2026:10:00:01 +0000] "GET /robots.txt HTTP/1.1" 200 120 "-" "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.4; +https://openai.com/gptbot"
Run against the live file on 30 October 2026, the script flagged all five GPTBot lines as outside and skipped the browser line:
$ python3 -I match_gptbot.py sample.log
list creationTime=2026-09-22T02:00:07.000000 prefixes=18
203.0.113.10 OUTSIDE Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.4; +https://openai.com/gptbot
203.0.113.77 OUTSIDE Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.4; +https://openai.com/gptbot
198.51.100.23 OUTSIDE Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.4; +https://openai.com/gptbot
8.8.8.8 OUTSIDE Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.4; +https://openai.com/gptbot
2001:db8::5 OUTSIDE Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.4; +https://openai.com/gptbot
Five of five outside is expected for invented addresses, but it does not prove the INSIDE branch works. So we ran the same script and log against a demo list holding 203.0.113.0/24 and 2001:db8::/32. The demo list is not an OpenAI file.
$ python3 -I match_gptbot.py sample.log demo-list.json
list creationTime=demo prefixes=2
203.0.113.10 INSIDE Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.4; +https://openai.com/gptbot
203.0.113.77 INSIDE Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.4; +https://openai.com/gptbot
198.51.100.23 OUTSIDE Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.4; +https://openai.com/gptbot
8.8.8.8 OUTSIDE Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.4; +https://openai.com/gptbot
2001:db8::5 INSIDE Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.4; +https://openai.com/gptbot
Two IPv4 lines and the IPv6 line match, the other two do not. The limit: this log is synthetic, so it shows the script works and says nothing about how often real requests fall outside. What should you do with an OUTSIDE line from your own log?
What does a GPTBot request outside the list mean?
A GPTBot user agent from an address outside gptbot.json is unverified, not proven fake. The user agent is a claim, and the file is a snapshot with a creationTime. OpenAI's crawler documentation (checked 1 November 2026) states no reverse DNS method, so the published IP file is the only address-based check it lists.
That absence is a reading of one page. We read the OpenAI crawler page in full on 1 November 2026 and searched it for "reverse", "rdns" and "hostname". Some third-party guides recommend reverse DNS for OpenAI crawlers. We could not confirm that from OpenAI's own page, so this article does not use it.
The page also gives no refresh interval for the lists and no publication date. The files carry only their creationTime values, which range from 2 January 2026 (OAI-SearchBot) to 27 October 2026 (ChatGPT-User) in the table above.
A thread on the OpenAI Developer Community, dated 17 November 2023, shows the same doubt. A user reported GPTBot requests from an address not in the documented ranges and asked whether the list is up to date. Another user replied the same day that anyone could send the GPTBot agent name and said they would ask about the list. The page shows no official answer. This is a user report, not confirmed by OpenAI.
In practice, a non-match leaves two readings: a spoofed header, or an address the file does not yet list. The script cannot tell them apart. Compare the request's behavior with your robots.txt, and check single addresses with the verify a single IP tool. The fake bot dataset shows how spoofed user agents look on this site, and the fake crawlers guide explains what to do with them. The GPTBot bot profile covers the token, and the ChatGPT robots.txt guide shows how to allow or block each OpenAI bot.
If you plan to block or allow by address, which list do you need?
Can I allowlist these ranges, and which list do I need?
Each OpenAI bot has its own list, and the sizes differ: 18 prefixes for GPTBot, 39 for OAI-SearchBot and 235 for ChatGPT-User. Allowlisting only gptbot.json does not cover search or user-triggered fetches, which use different tokens and different files.
OpenAI says each robots.txt setting is independent: "a webmaster can allow OAI-SearchBot in order to appear in search results while disallowing GPTBot." For search, its documentation recommends "allowing OAI-SearchBot in your site's robots.txt file and allowing requests from our published IP ranges below." For ChatGPT-User, it says "Because these actions are initiated by a user, robots.txt rules may not apply."
We compared the four lists with ipaddress. gptbot.json and searchbot.json share 6 identical prefixes. Every other pair shares none.
4.227.36.0/25, 74.7.175.128/25, 74.7.228.0/25, 74.7.230.0/25, 74.7.241.128/25, 74.7.244.0/25
An address inside one of those six prefixes therefore matches both lists, so the IP alone does not say which bot sent the request. The user agent has to do that part. See the OAI-SearchBot profile and the ChatGPT-User profile for the tokens.
Because OpenAI states no refresh schedule, fetch the files on a schedule you choose and compare the creationTime with your stored copy before you replace your allowlist. The takeaway: the file is the documented test, and a match proves the address, not the intent. Next step: paste any address from your log into the address check tool.
Common follow-up questions
How do I verify that a request is really GPTBot?
Check two things. The user agent must contain GPTBot, and the client IP must fall inside a prefix of OpenAI's gptbot.json. Both must hold. A matching user agent from an address outside the file is unverified. The script above automates the address test.
Does GPTBot have a reverse DNS name I can check?
OpenAI's crawler documentation, read in full on 1 November 2026, states no reverse DNS method for its crawlers. The published IP files are the only address-based check it lists. Third-party guides recommend reverse DNS, but they are not OpenAI's documentation.
Is the GPTBot IP list kept up to date?
OpenAI states no refresh interval. The gptbot.json file had a creationTime of 22 September 2026 when we read it on 1 November 2026. A 17 November 2023 community thread asked the same question and shows no official reply.
Do GPTBot and OAI-SearchBot share the same IP ranges?
Partly. On 1 November 2026 the two files shared 6 identical prefixes, out of 18 in gptbot.json and 39 in searchbot.json. The ChatGPT-User and OAI-AdsBot files shared none with any other list.
Does GPTBot support IPv6?
The published file lists no IPv6 prefix. On 1 November 2026 all 18 entries in gptbot.json used the ipv4Prefix key, and the other three OpenAI files held none either. The script above handles IPv6 if a list adds it.
Sources
- Overview of OpenAI Crawlers, https://developers.openai.com/api/docs/bots, Last checked: 1 November 2026
- GPTBot IP ranges, https://openai.com/gptbot.json, Last checked: 1 November 2026
- OAI-SearchBot IP ranges, https://openai.com/searchbot.json, Last checked: 1 November 2026
- ChatGPT-User IP ranges, https://openai.com/chatgpt-user.json, Last checked: 1 November 2026
- OAI-AdsBot IP ranges, https://openai.com/adsbot.json, Last checked: 1 November 2026
- Are the documented GPTBot IP egress ranges up-to-date? (OpenAI Developer Community), https://community.openai.com/t/are-the-documented-gptbot-ip-egress-ranges-up-to-date/509376, Last checked: 1 November 2026
Checked 1 November 2026.