Skip to main content

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples in this guide work on VillageSQL. Install Now →
IP geolocation in MySQL works by importing a database that maps IP ranges to locations, then querying it with range checks. The standard approach stores IP ranges as integers and uses BETWEEN. VillageSQL’s INET type makes the schema more expressive and handles IPv4 and IPv6 in the same table.

How IP Geolocation Works

There’s no MySQL function that maps an IP to a country. Geolocation is a lookup problem: you have a table of IP ranges — each row says “addresses from X to Y are in country Z” — and you find which range contains the incoming IP. Free databases like MaxMind GeoLite2 provide these ranges as CSV files you import into MySQL.

The Standard Approach: Integer Ranges

MaxMind GeoLite2 (and similar databases) ship with network as a CIDR string and the start/end of each range as integers. The integer approach is compact and index-friendly:
This is fast — the index on start_ip enables efficient range scanning. The limitation is that it only works for IPv4. A separate table (with VARBINARY(16) ranges) is needed for IPv6.

With VillageSQL: Unified IPv4/IPv6 with INET

VillageSQL’s INET type stores both IPv4 and IPv6 addresses with natural ordering, so you can use a single table for both families. inet_compare() takes the place of BETWEEN for range checks.

Storing by CIDR network (alternative schema)

If your GeoIP data provides CIDR blocks rather than start/end pairs, use CIDR for the network column and resolve containment via subnet queries:

Choosing an Approach

For pure IPv4 and maximum query speed, the INT UNSIGNED + BETWEEN approach is hard to beat. For schemas that need to handle both IPv4 and IPv6 in one table, INET with inet_compare is cleaner and avoids maintaining two parallel tables.

Comparing Geolocation Data Sources

The query schema is only half the decision — the data source determines accuracy, freshness, and cost. Here’s how the common options compare: Country-level accuracy figures are self-reported by providers and vary by region — Asia-Pacific and Latin American coverage tends to be lower than North America and Europe across all sources. Which to pick: MaxMind GeoLite2 is the standard starting point — it’s free, ships as flat files you import once, and lookups run entirely inside MySQL with no external dependency. For city-level accuracy in production, GeoIP2 Precision is the upgrade path. API-based sources (ip-api.com, ipinfo.io) are convenient for low-volume use but add HTTP latency and a rate-limit dependency to every lookup.

When to Use Each Approach

Importing GeoLite2 Data

MaxMind GeoLite2 (free, requires registration) provides CSV files. For the range-based schema:
MaxMind also provides a binary .mmdb format and official client libraries for languages like Python, Node.js, and Go that are faster than SQL lookups for high-volume scenarios.

Frequently Asked Questions

Should I do geolocation in MySQL or in application code?

For high-volume lookups (every HTTP request), application-layer geolocation using MaxMind’s .mmdb reader library is faster — binary search in memory, no SQL round-trip. SQL-based geolocation makes sense for batch analytics, reporting queries, and data pipelines that already run in MySQL.

How do I keep the GeoIP database current?

MaxMind updates GeoLite2 weekly. Script a periodic download and TRUNCATE + reload of the geolocation table. Alternatively, use MaxMind’s mmdbinspect or a refresh script to apply delta updates.

How accurate is IP geolocation in MySQL?

Accuracy depends entirely on the data source, not the MySQL schema. At the country level, MaxMind GeoLite2 (free) is accurate for roughly 98% of IPv4 addresses. At the city level it drops to around 80%. For higher accuracy, MaxMind’s paid GeoIP2 Precision product reaches ~99.8% country and ~85–90% city. No database is perfect — accuracy is typically lower for mobile networks, VPNs, and some Asia-Pacific ranges. The MySQL query approach has no effect on accuracy; you get exactly what the imported data says.

Can MySQL look up IP geolocation without a plugin or external API?

Yes. The standard approach — and what this guide covers — uses a GeoIP database (like MaxMind GeoLite2) imported into a regular MySQL table as integer ranges. Lookups are plain SQL BETWEEN queries. No plugin, no external API, no network call at query time. The only dependency is importing and periodically refreshing the flat CSV files from MaxMind. VillageSQL’s vsql_network_address extension adds an INET type for cleaner IPv4/IPv6 handling, but it’s not required for the basic approach.

Can I join geolocation with my access logs in one query?

Yes — that’s one of the main reasons to keep GeoIP data in MySQL:

Troubleshooting

See also