Docs · Guides

Visitor location.

Know which country a request comes from, with no outside service. Turn it on for a project and every request reaches your app with the visitor’s country, region and cookie-consent mode in headers.

Turn it on

Settings → Visitor location on the project. It is off until you switch it on.

The headers

X-Canner-IP-Country      CA         ISO country code, XX when unknown
X-Canner-IP-Region       QC         subdivision, when known
X-Canner-Consent-Mode    opt-in     opt-in or opt-out

The same values are also sent as X-Vercel-IP-Country, X-Vercel-IP-Country-Region and CF-IPCountry, so code written for those hosts works unchanged. Anything a visitor sends under these names is replaced, so your app can trust them.

X-Canner-Consent-Mode is opt-in for the EU and EEA, the UK, Switzerland, Canada, Brazil and South Korea, and for any visitor we cannot place. Everywhere else it is opt-out. It is a starting point, not legal advice: check it against the rules that apply to you.

import { headers } from "next/headers";

const h = await headers();
const mode = h.get("x-canner-consent-mode") ?? "opt-in"; // opt-in when the header is missing
app.use((req, res, next) => {
  res.locals.consent = req.get("x-canner-consent-mode") ?? "opt-in";
  next();
});

Good to know

  • Location comes from the visitor’s IP address, so a VPN shows the VPN’s country. Country is right most of the time; do not use it to block access.
  • The lookup runs on our servers from a local database. The address is not stored and nothing is sent to a third party.
  • Behind Cloudflare’s proxy, Cloudflare’s own country is used. Requests that claim Cloudflare headers from elsewhere are ignored.
  • A project with this on is not cached by Canner’s cache, so one country’s page is never served to another.
  • If your app already reacts to cf-ipcountry or x-vercel-* headers, check it before switching on.
  • Local development has no headers: default to opt-in.