The AWS ip-ranges.json format, explained

AWS publishes the public IP ranges it uses in a single JSON file, https://ip-ranges.amazonaws.com/ip-ranges.json. Each entry pairs an address range with a service code, a region and a network border group. This page explains every field, why the same address matches several entries, which entry to believe, and how and when the file changes.

This site reads the same file: your browser downloads it straight from AWS whenever you run a lookup. How it works has the details.

What the file looks like

An excerpt from the version published on 2026-09-24. The real file is a few megabytes, and the arrays hold thousands of entries.

{
  "syncToken": "1790232426",
  "createDate": "2026-09-24-06-47-06",
  "prefixes": [
    {
      "ip_prefix": "3.5.140.0/22",
      "region": "ap-northeast-2",
      "service": "AMAZON",
      "network_border_group": "ap-northeast-2"
    },
    ...
  ],
  "ipv6_prefixes": [
    {
      "ipv6_prefix": "2600:1f18::/33",
      "region": "us-east-1",
      "service": "EC2",
      "network_border_group": "us-east-1"
    },
    ...
  ]
}

Fields

FieldTypeMeaning
syncToken string The publication time as Unix epoch seconds, for example "1790232426" (2026-09-24 06:47:06 UTC). It is different in every version, so it is the value to use when you check whether the file has changed.
createDate string The same moment, in UTC, formatted YYYY-MM-DD-HH-MM-SS, for example "2026-09-24-06-47-06". It is not ISO 8601 and has no time zone marker; it is always UTC. AWS calls it the publication time, but the file usually reaches the download URL some time later (see updates).
prefixes array The IPv4 entries.
ipv6_prefixes array The IPv6 entries. Same shape, except that the range is in ipv6_prefix.
ip_prefix string An IPv4 range in CIDR notation, such as 3.5.140.0/22. AWS notes that it may announce a range to the internet as several smaller routes, so the routing table won't always show the same prefix.
ipv6_prefix string An IPv6 range in CIDR notation, such as 2600:1f18::/33. Compare parsed addresses rather than strings: the same address can be written in more than one way.
region string The AWS Region code, such as us-east-1, or GLOBAL for ranges whose traffic can come from, or go to, many Regions (see regions and GLOBAL).
service string A service code such as AMAZON, EC2, S3 or CLOUDFRONT. The service codes reference explains each one, including which codes mark traffic from AWS rather than services you connect to.
network_border_group string The set of Availability Zones, Local Zones or Wavelength Zones from which AWS advertises the range, or GLOBAL. For an ordinary regional range it equals the region code. Local Zones look like us-west-2-lax-1 (Los Angeles) and Wavelength Zones like us-east-1-wl1-bos-wlz-1 (AWS's Boston Wavelength Zone).

Writing a parser that keeps working

Shared ranges: one prefix, several services

The file has one entry per range and service, so a range used by several services is listed several times with the same region and border group:

jq -c '.prefixes[] | select(.ip_prefix == "3.5.140.0/22")' ip-ranges.json

{"ip_prefix":"3.5.140.0/22","region":"ap-northeast-2","service":"AMAZON","network_border_group":"ap-northeast-2"}
{"ip_prefix":"3.5.140.0/22","region":"ap-northeast-2","service":"S3","network_border_group":"ap-northeast-2"}
{"ip_prefix":"3.5.140.0/22","region":"ap-northeast-2","service":"EC2","network_border_group":"ap-northeast-2"}

That doesn't mean three services share the addresses. AWS's range overlap rules say that when one service runs on another's resources, the range is listed under both codes but used only by the first. Their example is exactly this case: a range tagged both S3 and EC2 is used exclusively by Amazon S3. To find ranges used by EC2 itself, take the EC2 ranges that no other service code claims.

AMAZON is different again. It is the catch-all: every address in the file is covered by an AMAZON entry, either on the same prefix or on a larger one around it. A range listed only as AMAZON means AWS uses it but doesn't say for what.

Nesting: ranges inside ranges

Besides sharing prefixes, entries nest. A small range for a specific service often sits inside a larger EC2 or AMAZON block, and the small range may have no AMAZON entry of its own. For 3.0.5.33 the file has:

3.0.5.32/29   EC2_INSTANCE_CONNECT   ap-southeast-1
3.0.0.0/15    AMAZON                 ap-southeast-1
3.0.0.0/15    EC2                    ap-southeast-1

The /29 is the part of the EC2 block that EC2 Instance Connect uses. Nesting also runs the other way: some small ranges tagged only AMAZON sit inside large EC2 blocks, carved out for something AWS doesn't name. And a regional range can sit inside a GLOBAL one (see below).

Choosing the most specific range

Because of sharing and nesting, an address usually matches several entries. This site picks one headline answer with the following rule, and always shows the other matches underneath:

  1. Collect every entry whose range contains the address.
  2. The most specific range wins. That is the one with the longest prefix (a /29 beats a /15). Larger ranges around it are context, not the answer.
  3. Within that range, a named service beats EC2, and EC2 beats AMAZON. This follows AWS's documented overlap rule, applied to the most specific range only.
  4. If only EC2 is left, say "EC2 address space", not "an EC2 instance". Load balancers, NAT gateways, Lambda and many other services use EC2 addresses too.
  5. If the most specific range is tagged only AMAZON, the service isn't disclosed. When a larger EC2 range encloses it, it is a carve-out: a range AWS has set aside inside EC2 space for something else. Reporting it as EC2 would be misleading.
  6. Take the region and border group from the most specific range. If an enclosing range is GLOBAL, mention that as well.

Worked examples from the file published on 2026-09-24 (ranges change, so a live lookup may differ):

AddressMatching ranges, most specific firstHeadline
3.18.1.10 3.16.0.0/14 AMAZON, EC2 · us-east-2 EC2 address space, US East (Ohio)
3.5.140.1 3.5.140.0/22 AMAZON, S3, EC2 · ap-northeast-2 Amazon S3 (the EC2 tag is dropped)
3.0.5.33 3.0.5.32/29 EC2_INSTANCE_CONNECT
3.0.0.0/15 AMAZON, EC2 · ap-southeast-1
EC2 Instance Connect
44.248.100.1 44.248.100.0/23 AMAZON
44.224.0.0/11 AMAZON, EC2 · us-west-2
Undisclosed service, carved out of EC2 space
64.252.81.1 64.252.81.0/24 AMAZON, EC2 · sa-east-1
64.252.64.0/18 AMAZON, CLOUDFRONT, CLOUDFRONT_ORIGIN_FACING · GLOBAL
EC2 address space in sa-east-1, inside a global CloudFront block

Two tempting shortcuts give wrong answers. Taking the first match depends on file order, which means nothing. Merging every tag that covers the address turns 44.248.100.1 into "EC2" and 3.0.5.33 into "EC2 and EC2 Instance Connect", hiding exactly the detail the small range was published to give.

Whatever the headline, a match identifies AWS's use of the range. It never identifies the AWS customer using an address.

Regions, GLOBAL and partitions

region is where AWS advertises the range, which isn't necessarily where anyone using it is. Some points that trip up parsers and people:

How and when the file changes

The file is served uncompressed, and its CORS header allows any website to read it. The server also honours Range requests, so you can read the first few bytes to check the syncToken without downloading everything:

curl -s -r 0-63 https://ip-ranges.amazonaws.com/ip-ranges.json

Change notifications (SNS)

AWS announces every change on the Amazon SNS topic

arn:aws:sns:us-east-1:806199016981:AmazonIpSpaceChanged

You can subscribe from any AWS account, in the us-east-1 Region, for example by email:

aws sns subscribe --region us-east-1 \
  --topic-arn arn:aws:sns:us-east-1:806199016981:AmazonIpSpaceChanged \
  --protocol email --notification-endpoint you@example.com

Each message carries create-time, synctoken, md5 (the hash of the new file) and url. AWS warns that notifications can arrive out of order, so compare synctoken values rather than trusting arrival order. Delivery also depends on your endpoint being available, and AWS suggests checking the file periodically as well. Anything that depends on current ranges should do both.

jq recipes

Download the file once, then query it locally:

curl -sO https://ip-ranges.amazonaws.com/ip-ranges.json

Version and publication time

jq -r '.syncToken, .createDate' ip-ranges.json

# createDate as ISO 8601
jq -r '.createDate | strptime("%Y-%m-%d-%H-%M-%S") | todate' ip-ranges.json
2026-09-24T06:47:06Z

Ranges for one service in one region

jq -r '.prefixes[] | select(.service == "S3" and .region == "eu-west-1") | .ip_prefix' ip-ranges.json
jq -r '.ipv6_prefixes[] | select(.service == "S3" and .region == "eu-west-1") | .ipv6_prefix' ip-ranges.json

EC2 ranges not claimed by another service

jq -r '.prefixes | group_by(.ip_prefix)[]
  | select(map(.service) | index("EC2") != null and all(. == "EC2" or . == "AMAZON"))
  | .[0].ip_prefix' ip-ranges.json

This applies AWS's overlap rule per prefix. It doesn't remove nested ranges: an EC2 block can still contain smaller ranges that belong to other services.

Prefixes listed under more than one service

jq -r '.prefixes | group_by(.ip_prefix)[] | select(length > 1)
  | [.[0].ip_prefix, (map(.service) | join(",")), .[0].region] | @tsv' ip-ranges.json

Border groups of a region

jq -r '[.prefixes[], .ipv6_prefixes[] | select(.region == "us-west-2") | .network_border_group] | unique[]' ip-ranges.json

The result lists the region itself plus its Local Zones and Wavelength Zones.

Every range containing an IPv4 address, most specific first

jq -r --arg ip 44.248.100.1 '
  def ip2n: split(".") | map(tonumber) | .[0]*16777216 + .[1]*65536 + .[2]*256 + .[3];
  ($ip | ip2n) as $n
  | [ .prefixes[]
      | (.ip_prefix | split("/")) as [$net, $len]
      | select(($net | ip2n) as $s | $n >= $s and $n < $s + pow(2; 32 - ($len | tonumber)))
      | . + {len: ($len | tonumber)} ]
  | group_by(.len) | reverse[]
  | [.[0].ip_prefix, (map(.service) | join(",")), .[0].region] | @tsv' ip-ranges.json

44.248.100.0/23   AMAZON       us-west-2
44.224.0.0/11     AMAZON,EC2   us-west-2

Output from the 2026-09-24 file. jq has no IPv6 arithmetic; for IPv6, use Python's ipaddress module as shown in how to check if an IP belongs to AWS, or paste the address into the lookup.

Other AWS IP lists

The CloudFront list

AWS serves CloudFront's IPv4 ranges on their own at d7uri8nf7uskq.cloudfront.net/tools/list-cloudfront-ips, as two arrays: CLOUDFRONT_GLOBAL_IP_LIST and CLOUDFRONT_REGIONAL_EDGE_IP_LIST. When we compared them, they matched the CLOUDFRONT entries in ip-ranges.json exactly: the global list is the GLOBAL entries and the regional edge list is the rest. It has no IPv6 ranges and no origin-facing section. Every IPv4 CLOUDFRONT_ORIGIN_FACING range sits inside one of its ranges, so an origin firewall built from it would work, but it would also admit all of CloudFront's edge space. To lock an origin to CloudFront, use the CLOUDFRONT_ORIGIN_FACING entries or the managed prefix list; the CloudFront guide covers that.

AWS-managed prefix lists

Inside AWS, security groups and route tables can reference AWS-managed prefix lists instead of raw CIDRs, and AWS keeps them current. Examples are com.amazonaws.global.cloudfront.origin-facing, com.amazonaws.region.s3 and com.amazonaws.region.dynamodb. A few services, such as AWS Ground Station, Amazon S3 Express One Zone and Amazon VPC Lattice, publish their ranges only this way. Reading a prefix list needs an AWS account:

aws ec2 describe-managed-prefix-lists --filters Name=owner-id,Values=AWS
aws ec2 get-managed-prefix-list-entries --prefix-list-id pl-0123456789abcdef0

Each list has a weight that counts against security group rule quotas. The CloudFront origin-facing list is heavy, so check AWS's documentation before adding it to a group that already has many rules.

The geolocation feed

ip-ranges.amazonaws.com/geo-ip-feed.csv gives a country, subdivision and city for AWS ranges, in the RFC 8805 geofeed format. AWS publishes it because a Local Zone isn't in the same place as its parent Region. A line looks like this:

1.178.4.0/23,US,US-VA,Ashburn,

Treat the city as the location of AWS's infrastructure, not of whoever uses an address.

Amazon SES sending ranges

Amazon SES mail servers are mostly absent from ip-ranges.json. The SES sending ranges are published in the SPF record of amazonses.com:

dig +short TXT amazonses.com | grep spf1

Sources