Locale Map
The locale map checker compares the Accept-Language header against the visitor's IP geolocation. Real browsers send a language preference that matches the country where the user is located. Bots and automated scripts commonly hardcode a generic locale (en-US, *, or none at all) regardless of where the request originates.
This is a cheap-phase checker. It reads geolocation data that was already resolved from the MMDB database and inspects a header. No additional I/O is needed.
How It Works
The checker parses the Accept-Language header according to RFC 7231, extracting the language tag with the highest quality value (q-factor). It then extracts the language code and optional region subtag from that tag.
The resolved geolocation provides a country ISO code and an ISO 639 language code for that country. The checker compares the two values. A mismatch between the declared locale and the geo-resolved country applies the ipAndHeaderMismatch penalty.
The checker also penalizes independently for:
- Missing header: the
Accept-Languageheader is absent entirely. - Missing geo data: the geolocation lookup returned no country or language data for the IP.
- Malformed header: the header value does not conform to the locale tag format.
Configuration
await defineConfiguration({
store: { main: { driver: 'sqlite', name: './bot-detector.db' } },
checkers: {
localeMapsCheck: {
enable: true,
penalties: {
ipAndHeaderMismatch: 20,
missingHeader: 20,
missingGeoData: 20,
malformedHeader: 30,
},
},
},
})
All weights live inside the penalties: {} sub-object.
20.20.20.30.Reason Codes
| Code | Trigger |
|---|---|
LOCALE_MISMATCH | The Accept-Language locale does not align with the geolocation country. Also applied for missing header, missing geo data, or malformed header. |
20). It contributes most value when combined with other cheap-phase signals such as proxy detection or missing headers. Visitors using VPNs may legitimately trigger this check because their IP resolves to a different country than their browser locale.ipAndHeaderMismatch and keeping malformedHeader at its default. Malformed locale headers are a much stronger bot signal than simple country/language mismatches.