# Your Matomo map shows every visitor as 'Unknown'? Set up GeoIP2 with the free GeoLite2 database

> If your self-hosted Matomo resolves visitors to 'Unknown' or one default country, you're almost always missing a GeoIP2 database. The old .dat downloads are dead and GeoLite2 now needs a free license key. Here's the current Matomo 5.x setup, why it broke, and how to keep it updating itself.

Published: 2026-07-20
Categories: Matomo Self-Hosting
Canonical: https://martez.io/blog/matomo-geoip2-geolite2-setup

---

<Callout type="tip" title="TL;DR">

Your map shows "Unknown" because Matomo has no readable GeoIP2 database, not because tracking is broken. On Matomo 5, create a free MaxMind license key (answer "No" to the GeoIP Update question), paste the `GeoLite2-City` download URL into Administration → System → Geolocation, and set the provider to `DBIP / GeoIP 2 (Php)`. Keep your archiving cron running so the database refreshes itself instead of going stale. One thing to rule out first: if every visitor resolves to the same IP, that's a proxy/`X-Forwarded-For` problem, and no database will fix it.

</Callout>

If you've opened Visitors → Locations in a self-hosted Matomo and found every visitor resolving to "Unknown," a single default country, or nothing at all on the map, the tracking isn't broken. Matomo is recording the visits fine. What's usually missing is the geolocation database it needs to turn an IP address into a country, region, and city: either there's no GeoIP2 database installed, or the one you have sits in an old format Matomo can no longer read.

The other way people land here is an old `wget` cron job that used to download `GeoLiteCity.dat.gz` and now fails quietly. The URL 404s or bounces to a login page, and nobody notices until the map goes blank. Same root cause, different symptom. The fix is the same either way: move to Matomo's current GeoIP2 workflow with a free MaxMind license key, and let Matomo refresh the database for you.

## What actually changed

Two things shifted, and most of the older tutorials never caught up.

The first is that the old `.dat` databases are gone. MaxMind removed the free GeoLite Legacy builds (`GeoLiteCity`, `GeoLiteCountry`) on January 2, 2019, and retired its broader paid GeoIP Legacy `.DAT` products later. Matomo dropped its old GeoIP plugin in favour of GeoIP2, which reads the modern binary `.mmdb` format. Any guide that tells you to download a `.dat` file is pointing at something that no longer exists. If a script of yours still fetches one, that script is the problem.

The second is that free GeoLite2 now needs an account. Since the end of 2019 you can't download GeoLite2 anonymously. MaxMind wants a free account and a license key, which you pass inside the download URL. The data is still free; you're authenticating, not paying. This is the step the old `wget` lines skipped, which is exactly why they break.

The plugin you need, GeoIp2, ships bundled with Matomo 5.x, and Matomo can download and refresh the database on a schedule for you. In almost every case there's no custom shell script left to write.

<Callout type="question" title="First, check what IP Matomo is recording">
A missing database isn't the only reason a map goes blank. Open Visitors → Visits Log and look at the IP on a few recent visits. If you see real, varied public addresses, a GeoIP2 database is what you're missing. Continue below. But if every visit shares the same IP, a private RFC1918 range (`10.x`, `192.168.x`), `0.0.0.0`, or your proxy/server's own address, no geolocation database will save you. Matomo is geolocating the wrong IP. Fix proxy IP detection first (the `proxy_client_headers` setting and your reverse proxy's `X-Forwarded-For` handling), then come back to this.
</Callout>

## The fix on Matomo 5.x

### 1. Create a free MaxMind account and a license key

Sign up at maxmind.com for the free GeoLite2 product and confirm your email. In the account portal, go to Manage License Keys → Generate new license key, give it a description like `Matomo`, and answer No to "Will this key be used for GeoIP Update?". That last answer matters. "No" gives you a key that works with the direct download URL Matomo uses; "Yes" produces a key tied to MaxMind's separate `geoipupdate` protocol, which the built-in updater doesn't touch. Copy the key right away, because MaxMind shows it to you exactly once.

### 2. Build your download URL

Take this template and append your key to the end:

```
https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&suffix=tar.gz&license_key=YOUR_LICENSE_KEY
```

`GeoLite2-City` gives you country, region, and city. If you only care about country and want a smaller, faster file, swap in `edition_id=GeoLite2-Country`. If you just generated the key, give it a minute or two before the link goes live. Worth a sanity check first: paste the finished URL into a browser and it should immediately start downloading a `tar.gz`. If it returns an error instead, the key is wrong, not active yet, or the URL is malformed. Fix that before you touch Matomo.

### 3. Point Matomo at it

Log in as a super user and open Administration (the cog) → System → Geolocation. Scroll to the "Setup automatic updates of GeoIP databases" section, paste your full URL into the "Location Database Download URL" field, choose weekly or monthly, and save. Matomo downloads the `tar.gz`, unpacks it, and installs the `.mmdb` into its `misc/` directory. You'll end up with something like `misc/GeoLite2-City.mmdb` under your Matomo root.

### 4. Activate the GeoIP2 provider

Back at the top of the same Geolocation page, select "DBIP / GeoIP 2 (Php)" as your location provider and save. That's the right pick on shared hosting and most installs. It reads the `.mmdb` in pure PHP, and it's faster still if your host has the `maxminddb` PHP C extension, though it works fine without one. Only choose "DBIP / GeoIP 2 (HTTP Server Module)" if you've actually installed the Apache or Nginx `mod_maxminddb` module and configured the server to set the lookup variables. If you haven't, that option has no data to read.

One provider covers both MaxMind and DB-IP databases. Matomo merged them under a single GeoIP2 reader, which is why the label says "DBIP / GeoIP 2" even though you fed it a MaxMind file.

## Make sure it actually keeps updating itself

Here's the part that bites people six months later, so it's worth stating plainly: Matomo's geolocation auto-updates ride on its scheduled tasks, and those run whenever the archiving process runs. The weekly or monthly refresh isn't a separate timer. In production that scheduled run is almost always `console core:archive` fired by cron (web cron counts too). No scheduled archive run, no auto-update, and the database you installed today slowly goes stale as MaxMind reassigns IP ranges.

So if you haven't set up the [Matomo archiving cron](/blog/set-up-matomo-cron-archiving) yet, do that first and the GeoIP refresh rides along for free. And if archiving is set up but [throwing an "invalid response" or failing silently](/blog/matomo-cron-archiving-invalid-response), fix that too, because a broken archiving run takes the geolocation update down with it.

Two other things quietly break this. The license key can stop working: if updates start failing months in, check the key's status in your MaxMind account, replace it if it's been revoked, and confirm you haven't hit the GeoLite download limit, then update the URL in Matomo. And outbound requests get blocked: if your Matomo sits behind a [reverse proxy or a locked-down firewall](/blog/self-host-matomo-reverse-proxy-502), confirm the server itself can reach `download.maxmind.com`, follow the HTTPS redirect, and reach the Cloudflare R2 host MaxMind now serves the actual file from (`mm-prod-geoip-databases.…r2.cloudflarestorage.com`). The browser test in step 2 runs from your machine, not Matomo's, and the two don't always share the same egress. From the server itself, `curl -sI "$YOUR_URL"` should end in a `200` after the redirect.

<Callout type="info" title="This fixes new visits, not old ones">
Matomo geolocates a visit when it's tracked, so the database you just installed only helps visits recorded from now on. Last month's "Unknown" rows stay Unknown on their own. To backfill them, run `php ./console usercountry:attribute START_DATE,END_DATE` (for example `2026-01-01,2026-05-31`) from your Matomo root, then reprocess the reports for that range so the Locations data reflects the re-attributed visits.
</Callout>

## Verify it worked

Three quick checks:

- On the Geolocation page, the provider you selected should show a working status and a sample lookup (usually your own IP) resolving to the right place.
- Record a fresh visit and open Visitors → Locations. Countries, regions, and cities should populate, and the [country flags on the map](/blog/matomo-country-flags-geolocation) should fill in instead of reading as unknown.
- After the next scheduled archiving run, check the modification date on `misc/GeoLite2-City.mmdb`. A recent timestamp proves the auto-updater is wired up, not just the first manual download.

## What we'd actually do

For most self-hosted installs the whole job is short: free MaxMind account, a license key with "No" to the GeoIP Update question, the `GeoLite2-City` download URL pasted into the Geolocation admin, set to weekly, provider set to "DBIP / GeoIP 2 (Php)", and a working archiving cron behind it. Don't hand-roll a `wget` script. There's nothing left for one to do that the built-in updater doesn't do more reliably.

If you have a hard requirement for OS-level updates, say you manage the database centrally across a few apps, use MaxMind's official `geoipupdate` package with a `GeoIP.conf` (this is where the "Yes, for GeoIP Update" key belongs):

```ini
# /etc/GeoIP.conf
AccountID YOUR_ACCOUNT_ID
LicenseKey YOUR_GEOIP_UPDATE_KEY
EditionIDs GeoLite2-City
```

There's a catch worth knowing: Matomo doesn't give you a field to point at an arbitrary path like `/var/lib/GeoIP/`. It reads from its own `misc/` directory. So either configure `geoipupdate` to write straight into `path/to/matomo/misc/`, or copy or symlink the resulting `GeoLite2-City.mmdb` into `path/to/matomo/misc/GeoLite2-City.mmdb` after each run, with permissions the Matomo PHP user can read. On Docker that usually means a bind mount or symlink from the host file into the container's `misc/`. That's the exception, though, not the default. And if you'd rather not create a MaxMind account at all, Matomo can one-click download a free DB-IP database with no account whatsoever. It's a notch less accurate at city level than GeoLite2, but it's genuinely zero-config and a fine place to start.

[Martez](/?utm_source=martez&utm_medium=blog&utm_campaign=matomo-geoip2-geolite2-setup) connects Matomo with Meta Ads and Google Ads so ROAS, CLV, and attribution sit next to your web analytics instead of in a separate spreadsheet. It's in private beta. [Join the waitlist](/signup?utm_source=martez&utm_medium=blog&utm_campaign=matomo-geoip2-geolite2-setup) if that's relevant.

Get the key, paste the URL, check the cron. Your map fills itself in from there.
