Skip to content

tn3w/ip2c

Repository files navigation

ip2c

Fast, daily-rebuilt IP to country databases.

publish release license

IPv4 + IPv6 to two-letter ISO-3166 country code.
Merged from IPFire, DB-IP, IP2Location and iptoasn. Reserved/unknown to ZZ.

Databases

Latest release ships three files:

File Size Best for
country.bin ~1.8MB fastest, mmap-friendly binary
country.csv ~7.5MB lossless text, sorted, bisectable
country-small.csv ~2.6MB smallest, lossy (coarsened) text
curl -LO https://github.com/tn3w/ip2c/releases/latest/download/country.bin

Quick start

Two zero-dependency modules in golf/. load once, then lookup:

import { readFileSync } from "node:fs"
import { load, lookup } from "./golf/bin"

const db = load(readFileSync("country.bin"))

lookup(db, "8.8.8.8") // "US"
lookup(db, "2606:4700:4700::1111") // "US"
import { readFileSync } from "node:fs"
import { load, lookup } from "./golf/csv"

const db = load(readFileSync("country.csv", "utf8"))
lookup(db, "1.1.1.1") // "CN"

CLI: npm run lookup country.bin 8.8.8.8 2606:4700:4700::1111

IPv4-only or IPv6-only

The CSV splits at the 6 marker line. load fills only the section kept; the other family returns ZZ.

sed '/^6$/Q' country.csv > country-v4.csv # 3.2MB
sed -n '/^6$/,$p' country.csv > country-v6.csv # 4.4MB

Cloudflare Worker

Optional. country.bin bundles into a Worker for sub-millisecond, zero-subrequest lookups.

GET /?ip=1.1.1.1     {"ip":"1.1.1.1","country":"CN"}
GET /                country of the caller (CF-Connecting-IP)

Live instance: ip2c.tn3w.dev.

Deploy your own:

npm install
npm run build && npx wrangler deploy

Automation

  • publish.yml daily: builds the files, cuts a Release (keeps the latest 5), redeploys the Worker.
  • deploy.yml on src/** push: redeploys the Worker with the latest released country.bin.

Deploys need repo secrets CLOUDFLARE_API_TOKEN (Workers Scripts: Edit) and CLOUDFLARE_ACCOUNT_ID; without them they no-op.

How it works

scripts/build.ts merges the sources by priority into per-family breakpoint tables, then emits the three files. Lookup is a binary search over sorted range starts.

  • .csv 4/6 marker lines, then <start><CC> rows; each start owns the range up to the next. v4 drops trailing .0, v6 is the /64 upper-64.
  • .bin magic IPC2, little-endian. Per family: block keys + offsets + varint body; bisect keys, seek, walk up to 64 rows. Layout in src/lib/build.ts.

License

Apache-2.0