Device Emulation Guide: Mobile, Tablet, and Desktop Profiles
How to emulate complete device identities including touch events, screen metrics, and mobile UA for authentic mobile and desktop profiles.
Introduction
A browser reveals its device through dozens of signals: screen dimensions, device pixel ratio, touch capabilities, device memory, GPU characteristics, input modalities, and more. These signals form a coherent picture of the physical device running the browser. A Pixel 7 has specific screen dimensions, a specific DPR, a specific number of touch points, a specific GPU, and specific memory. When these signals are consistent, the browser appears to be running on real hardware. When they conflict, the inconsistency is visible.
BotBrowser loads complete device profiles captured from real hardware. When a mobile profile is loaded on a desktop system, all device signals update consistently because they all come from the same source device. There is no mix-and-match, no manual configuration of individual properties, and no risk of signal conflicts.
Privacy Impact: Why Device Signals Matter
Device emulation is important for several reasons beyond just appearing as a mobile or desktop browser.
Tracking systems use device signals as part of their fingerprinting process. The combination of screen resolution, DPR, touch support, device memory, GPU renderer, and CPU core count creates a device-level fingerprint that persists across sessions. Controlling these signals is necessary for maintaining consistent browser identities and for studying how tracking systems use device characteristics.
E-commerce and content platforms serve different experiences based on the detected device. Mobile users may see different pricing, different layouts, and different content selections. Privacy researchers need device-accurate emulation to study these practices reliably.
For multi-account management, device diversity is important. Having every identity present as the same device model with identical screen dimensions is suspicious. Using a variety of device profiles, mixing desktop and mobile, different screen sizes, and different DPR values, creates natural variation.
Technical Background
Device Signals in the Browser
The browser exposes device characteristics through multiple APIs:
Screen dimensions: screen.width, screen.height, screen.availWidth, screen.availHeight report the physical display size. window.innerWidth and window.innerHeight report the viewport. window.outerWidth and window.outerHeight include browser chrome.
Device pixel ratio: window.devicePixelRatio reports the ratio between CSS pixels and physical pixels. Desktop displays typically have DPR of 1.0 or 1.25. Mobile devices range from 2.0 to 3.5 or higher. Retina MacBooks report 2.0.
Touch capabilities: navigator.maxTouchPoints reports the maximum simultaneous touch points (0 for desktop, 5-10 for mobile). The ontouchstart event handler availability on the window object indicates touch support. CSS media queries (pointer: coarse) and (hover: none) distinguish touch-primary from pointer-primary input.
Device memory: navigator.deviceMemory reports approximate RAM in GB. Mobile devices typically report 4-8 GB, desktops 8-16 GB.
Hardware concurrency: navigator.hardwareConcurrency reports the number of CPU cores available. Mobile devices typically report 4-8, desktops 4-16 or more.
Connection info: navigator.connection provides network type, effective type, downlink speed, and RTT. Mobile devices often report different network characteristics than desktop systems.
GPU: The WebGL renderer string identifies the graphics hardware. Mobile GPUs (Adreno, Mali, PowerVR, Apple GPU) differ completely from desktop GPUs (NVIDIA GeForce, AMD Radeon, Intel UHD).
Signal Consistency Requirements
These signals must be internally consistent. A browser reporting maxTouchPoints: 10 but (pointer: fine) and (hover: hover) contains a contradiction. A browser with a 412px screen width but 16 GB device memory and an NVIDIA GPU combines mobile screen dimensions with desktop hardware characteristics. These inconsistencies make it clear that individual signals have been spoofed rather than coming from a real device.
Common Approaches and Their Limitations
Chrome DevTools Device Emulation
Chrome DevTools Protocol provides device emulation through Emulation.setDeviceMetricsOverride. This sets viewport dimensions, DPR, and touch support. Playwright and Puppeteer expose this through their device emulation APIs.
Limitations:
- Does not change
navigator.platformor User-Agent data beyond what is explicitly set - WebGL renderer strings still report the desktop GPU
navigator.deviceMemoryandnavigator.hardwareConcurrencyremain at desktop values- Touch emulation is surface-level, not engine-level
- Font availability remains desktop-specific
- Media queries may not fully align with the emulated device
Manual Property Overrides
You can override individual properties through JavaScript injection:
Object.defineProperty(navigator, 'maxTouchPoints', { get: () => 10 });
Object.defineProperty(navigator, 'deviceMemory', { get: () => 4 });
This changes the JavaScript-visible values but does not affect the actual behavior of the browser. CSS media queries, rendering pipeline behavior, and HTTP headers are unaffected by JavaScript property overrides.
Viewport-Only Approaches
Setting a mobile viewport size (e.g., 412x915) through the automation framework changes the layout but does not change any other device signal. The browser still reports desktop screen dimensions, desktop DPR, zero touch points, and desktop GPU information.
BotBrowser's Approach
BotBrowser profiles are captured from real devices, meaning all device signals come from the same physical hardware. When loaded on any system, these signals are applied together at the engine level, ensuring complete internal consistency.
Profile-Based Device Identity
Each profile contains a snapshot of the device's characteristics:
- Screen dimensions (width, height, available width, available height)
- Device pixel ratio
- Touch capabilities (maxTouchPoints, touch event support)
- Device memory
- Hardware concurrency
- GPU renderer and vendor strings
- Platform-specific navigator properties
- Window chrome dimensions (for calculating outer dimensions)
All of these signals are applied as a unit, not individually. This eliminates the risk of signal conflicts.
Engine-Level Touch Support
When a mobile profile is loaded, touch support is enabled at the Chromium engine level, not through JavaScript injection:
navigator.maxTouchPointsreturns the device's actual valueontouchstartis natively available on the window object- CSS media queries
(pointer: coarse)and(hover: none)evaluate correctly in the style engine - Touch event constructors and properties behave exactly as they do on the real device
- The
InputDeviceCapabilitiesAPI reports touch correctly
Desktop, Mobile, and Tablet Profiles
BotBrowser supports profiles from all device categories:
Desktop profiles: Large screens (1920x1080, 2560x1440), DPR of 1.0-2.0, zero touch points, fine pointer, desktop GPU, 8-16 GB memory.
Mobile profiles: Small screens (412x915, 390x844), DPR of 2.0-3.5, touch support with 5-10 points, coarse pointer, mobile GPU, 4-8 GB memory.
Tablet profiles: Medium screens (1024x1366, 820x1180), DPR of 2.0, touch support, sometimes both coarse and fine pointer, mobile or integrated GPU.
Window and Screen Configuration
BotBrowser provides fine-grained control over window and screen properties through CLI flags:
# Use the profile's captured dimensions (default for headless)
--bot-config-window=profile
--bot-config-screen=profile
# Specific dimensions
--bot-config-window=1920x1080
--bot-config-screen=2560x1440
# Full JSON customization
--bot-config-window='{"innerWidth":1920,"innerHeight":1080,"devicePixelRatio":2}'
Configuration and Usage
Mobile Device Profile
chrome --bot-profile="/profiles/pixel7-chrome-130.enc" \
--user-data-dir="$(mktemp -d)"
Playwright Integration
const { chromium } = require('playwright-core');
(async () => {
const browser = await chromium.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/profiles/pixel7-chrome-130.enc',
],
headless: true,
});
// Important: do not set viewport - let the profile control it
const context = await browser.newContext();
const page = await context.newPage();
const metrics = await page.evaluate(() => ({
screenWidth: screen.width,
screenHeight: screen.height,
innerWidth: window.innerWidth,
innerHeight: window.innerHeight,
dpr: devicePixelRatio,
touchPoints: navigator.maxTouchPoints,
touchStart: 'ontouchstart' in window,
pointer: matchMedia('(pointer: coarse)').matches ? 'coarse' : 'fine',
hover: matchMedia('(hover: none)').matches ? 'none' : 'hover',
memory: navigator.deviceMemory,
cores: navigator.hardwareConcurrency,
}));
console.log('Device metrics:', metrics);
await browser.close();
})();
Puppeteer with Desktop Profile
const puppeteer = require('puppeteer-core');
(async () => {
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/profiles/win11-desktop-1080p.enc',
],
headless: true,
defaultViewport: null, // Let the profile control viewport
});
const page = await browser.newPage();
await page.goto('https://example.com');
await browser.close();
})();
Custom Window Size with Profile
# Override just the window size, keep everything else from the profile
chrome --bot-profile="/profiles/win11-chrome-130.enc" \
--bot-config-window=1440x900 \
--bot-config-screen=1920x1080
Verification
Verify device emulation by checking the full range of device signals:
const page = await context.newPage();
await page.goto('https://example.com');
const deviceCheck = await page.evaluate(() => ({
// Screen
screen: {
width: screen.width,
height: screen.height,
availWidth: screen.availWidth,
availHeight: screen.availHeight,
},
// Window
window: {
innerWidth: window.innerWidth,
innerHeight: window.innerHeight,
outerWidth: window.outerWidth,
outerHeight: window.outerHeight,
dpr: window.devicePixelRatio,
},
// Touch
touch: {
maxTouchPoints: navigator.maxTouchPoints,
ontouchstart: 'ontouchstart' in window,
pointerCoarse: matchMedia('(pointer: coarse)').matches,
hoverNone: matchMedia('(hover: none)').matches,
},
// Hardware
hardware: {
deviceMemory: navigator.deviceMemory,
hardwareConcurrency: navigator.hardwareConcurrency,
},
}));
console.log('Device verification:', JSON.stringify(deviceCheck, null, 2));
Best Practices
- Always use
defaultViewport: nullin Playwright and Puppeteer. This lets the profile control viewport dimensions. Framework viewport settings override profile values, breaking consistency. - Choose device profiles that match your use case. For general web automation, use common device models. For mobile testing, use profiles from popular phone models.
- Do not mix manual overrides with profiles. Let the profile control the full device identity. Manual overrides (like setting a custom viewport on a mobile profile) risk creating signal inconsistencies.
- Verify all signal categories. Check screen, touch, hardware, and GPU signals together, not individually.
- Use
--bot-config-windowand--bot-config-screenfor controlled overrides. When you need specific dimensions, these flags adjust the display properties while keeping all other signals consistent. - Match device to use case. For e-commerce testing, use consumer phone profiles. For enterprise testing, use desktop profiles with typical office monitor resolutions.
Frequently Asked Questions
Does BotBrowser generate actual touch events?
BotBrowser enables touch support at the engine level, meaning maxTouchPoints, ontouchstart, and CSS media queries all report correctly. To generate touch event sequences (tap, swipe, pinch), use your automation framework's touch input APIs. Playwright provides page.touchscreen.tap() and Puppeteer provides similar methods.
What happens if I set a viewport in Playwright with a mobile profile?
Setting a viewport through Playwright or Puppeteer overrides the profile's window dimensions. This can create inconsistencies between innerWidth/innerHeight (set by the framework) and screen.width/screen.height (set by the profile). Use defaultViewport: null to avoid this.
Can I customize screen dimensions while keeping other device signals?
Yes. Use --bot-config-window and --bot-config-screen to override display dimensions while keeping touch, memory, GPU, and other signals from the profile.
How does devicePixelRatio work with screenshots?
When taking screenshots, the actual pixel dimensions of the image are width * devicePixelRatio by height * devicePixelRatio. A 412px wide mobile viewport with DPR 2.625 produces screenshots that are 1081 pixels wide.
Do tablet profiles have touch support?
Yes. Tablet profiles include touch support (typically maxTouchPoints: 10) along with tablet-appropriate screen dimensions and DPR values.
Can I use different device profiles for different contexts in the same browser?
Device characteristics are set at the browser instance level through the profile. Different contexts within the same browser share the same device signals. For different device identities, launch separate browser instances with different profiles.
What GPU strings do mobile profiles report?
Mobile profiles report the GPU from the source device. Common examples include "Adreno (TM) 730" for Qualcomm-based devices, "Mali-G710" for Samsung Exynos devices, and "Apple GPU" for iPhones.
Summary
Device emulation in BotBrowser provides complete, consistent device identities through profiles captured from real hardware. All device signals, from screen dimensions and touch capabilities to GPU strings and device memory, come from the same source device, ensuring internal consistency without manual configuration.
For related topics, see Android Emulation for mobile-specific emulation, Screen and Window Fingerprinting for screen signal details, and Cross-Platform Profiles for running profiles across operating systems.