device-type: Device detection module for NGINX
Requires the Pro plan (or higher) of the GetPageSpeed NGINX Extras subscription.
Installation
You can install this module in any RHEL-based distribution, including, but not limited to:
- RedHat Enterprise Linux 7, 8, 9 and 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 and Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-device-type
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-device-type
Enable the module by adding the following at the top of /etc/nginx/nginx.conf:
load_module modules/ngx_http_device_type_module.so;
This document describes nginx-module-device-type v1.0.0 released on Feb 15 2026.
High-performance device detection for NGINX — directly at the edge.
Why This Module?
Device detection is critical for:
- Adaptive serving — serve mobile-optimized assets without redirects
- Cache segmentation — vary cached content by device type
- Bot management — block scrapers, rate-limit crawlers, allow search engines
- AI crawler control — identify and manage GPTBot, ClaudeBot, and other AI training bots
- Analytics enrichment — pass device context to backends
Traditional solutions require external API calls, adding latency and cost. This module performs detection in-process using precompiled regex patterns — no network round-trips, no per-request fees.
Features
| Feature | Description |
|---|---|
| 22 NGINX variables | Device type, browser, OS, bot classification — all as native variables |
| 4,000+ detection patterns | Comprehensive coverage maintained by GetPageSpeed |
| Client Hints support | High-accuracy detection with modern browsers |
| AI crawler detection | Identify GPTBot, ClaudeBot, Anthropic-AI, CCBot, and 50+ AI bots |
| Bot categorization | Classify as search_engine, ai_crawler, crawler, monitoring, scraper |
| JSON output | Complete detection result as a single JSON variable |
| Zero configuration | Load the module, use the variables — no directives needed |
| Per-request caching | Detection runs once per request, results cached in module context |
Pattern Statistics
- 800+ bot patterns with category, producer, and AI crawler flag
- 500+ browser patterns with version extraction and engine detection
- 300+ OS patterns with version and family classification
- 2,000+ device patterns for brand and model detection
Quick Start
1. Load the Module
load_module modules/ngx_http_device_type_module.so;
2. Use the Variables
server {
# Serve different content by device
location / {
if ($is_mobile) {
rewrite ^(.*)$ /m$1 last;
}
}
# Block AI crawlers
location /content/ {
if ($is_ai_crawler) {
return 403;
}
proxy_pass http://backend;
}
# Debug endpoint
location = /device {
default_type application/json;
return 200 $device_json;
}
}
Variables Reference
Device Type
| Variable | Values | Description |
|---|---|---|
$device_type |
mobile, tablet, desktop, tv, console, car, wearable, camera, peripheral, bot |
Primary classification |
$is_mobile |
1 / 0 |
Phone or mobile-only browser |
$is_tablet |
1 / 0 |
Tablet device |
$is_desktop |
1 / 0 |
Desktop or laptop |
$is_bot |
1 / 0 |
Bot or crawler |
$is_tv |
1 / 0 |
Smart TV |
$is_console |
1 / 0 |
Gaming console |
$is_wearable |
1 / 0 |
Wearable device |
Device Details
| Variable | Example | Description |
|---|---|---|
$device_brand |
Apple, Samsung, Google |
Device manufacturer |
$device_model |
iPhone 15, Galaxy S24, Pixel 8 |
Device model |
Browser
| Variable | Example | Description |
|---|---|---|
$browser_name |
Chrome, Firefox, Safari |
Browser name |
$browser_version |
120.0.0.0 |
Full version string |
$browser_family |
Chrome, Firefox, Safari |
Browser family |
$browser_engine |
Blink, Gecko, WebKit |
Rendering engine |
Operating System
| Variable | Example | Description |
|---|---|---|
$os_name |
Windows, Android, iOS |
OS name |
$os_version |
14, 17.2, 11 |
OS version |
$os_family |
Windows, Android, Unix, iOS, macOS |
OS family |
Bot Classification
| Variable | Example | Description |
|---|---|---|
$bot_name |
Googlebot, GPTBot, ClaudeBot |
Bot identifier |
$bot_category |
search_engine, ai_crawler, crawler |
Bot category |
$bot_producer |
Google, OpenAI, Anthropic |
Bot operator |
$is_ai_crawler |
1 / 0 |
AI training/search crawler |
JSON Output
| Variable | Description |
|---|---|
$device_json |
Complete detection result as JSON |
Example JSON:
{
"type": "mobile",
"browser": {"name": "Chrome", "version": "120.0", "engine": "Blink"},
"os": {"name": "Android", "version": "14", "family": "Android"},
"device": {"brand": "Google", "model": "Pixel 8"},
"bot": null
}
Bot detection JSON:
{
"type": "bot",
"browser": {"name": "", "version": "", "engine": ""},
"os": {"name": "", "version": "", "family": ""},
"device": {"brand": "", "model": ""},
"bot": {"name": "GPTBot", "category": "ai_crawler", "producer": "OpenAI", "is_ai": true}
}
Use Cases
Adaptive Content Serving
# Serve mobile-optimized pages
location / {
set $variant "desktop";
if ($is_mobile) { set $variant "mobile"; }
if ($is_tablet) { set $variant "tablet"; }
proxy_pass http://backend;
proxy_set_header X-Device-Variant $variant;
}
Cache Key Variation
# Vary cache by device type
proxy_cache_key "$scheme$request_uri|$device_type";
# Or just mobile vs desktop
proxy_cache_key "$scheme$request_uri|$is_mobile";
Bot Management
# Block AI training crawlers
location / {
if ($is_ai_crawler) {
return 403 "AI crawlers not permitted";
}
}
# Rate limit scrapers, allow search engines
limit_req_zone $binary_remote_addr zone=scraper:10m rate=1r/s;
location / {
if ($bot_category = "scraper") {
limit_req zone=scraper;
}
proxy_pass http://backend;
}
Analytics Headers
location /api/ {
proxy_set_header X-Device-Type $device_type;
proxy_set_header X-Device-Brand $device_brand;
proxy_set_header X-Browser $browser_name;
proxy_set_header X-OS $os_name;
proxy_set_header X-Is-Bot $is_bot;
proxy_pass http://backend;
}
Debug Endpoint
location = /debug/device {
default_type text/plain;
return 200 "Type: $device_type
Mobile: $is_mobile
Tablet: $is_tablet
Desktop: $is_desktop
Bot: $is_bot ($bot_name)
AI Crawler: $is_ai_crawler
Browser: $browser_name $browser_version
Engine: $browser_engine
OS: $os_name $os_version ($os_family)
Device: $device_brand $device_model
";
}
Client Hints
For improved detection accuracy with Chromium-based browsers, advertise Client Hints:
add_header Accept-CH "Sec-CH-UA, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version";
add_header Critical-CH "Sec-CH-UA-Mobile";
The module processes these Client Hints:
| Header | Used For |
|---|---|
Sec-CH-UA |
Browser brand and version |
Sec-CH-UA-Mobile |
Mobile indicator (?1 = mobile) |
Sec-CH-UA-Model |
Device model (tablet/phone hints) |
Sec-CH-UA-Platform |
OS name |
Sec-CH-UA-Platform-Version |
OS version |
Client Hints provide more accurate information than User-Agent parsing and are the future of device detection.
Detection Priority
The module evaluates signals in this order:
- Bot detection — regex match against 800+ bot patterns
- Client Hints — if present, used for mobile/tablet/browser/OS detection
- Quick UA checks — fast substring matches for iPad, iPhone, PlayStation, etc.
- Full device patterns — 2,000+ regex patterns for brand/model
- Android tablet heuristic — Android without "Mobile" token → tablet
- Mobile fallback — "Mobile" token → mobile
- Browser detection — 500+ patterns with version capture
- Engine detection — Blink, Gecko, WebKit, etc.
- OS detection — 300+ patterns with family classification
Results are cached per-request in the module context.
Comparison with Alternatives
| Feature | This Module | 51Degrees | WURFL | DeviceAtlas |
|---|---|---|---|---|
| In-process detection | ✅ | ✅ | ✅ | ❌ (Cloud) |
| No per-request cost | ✅ | ❌ | ❌ | ❌ |
| AI crawler detection | ✅ | ❌ | ❌ | ❌ |
| Bot categorization | ✅ | Limited | Limited | Limited |
| Client Hints | ✅ | ✅ | ✅ | ✅ |
| JSON output | ✅ | ❌ | ❌ | ❌ |
| Dynamic module | ✅ | ✅ | ✅ | N/A |
| ## |