Introduction
Mobile traffic is a major part of modern web applications. A website can work perfectly on desktop and still fail on a smartphone because of a broken menu, incorrect viewport, oversized buttons, horizontal scrolling, or a form that is difficult to use.
This makes Playwright Mobile Emulation an important skill for QA Automation Engineers and SDETs.
In this playwright mobile emulation tutorial, you will learn how to simulate mobile browser environments using Playwright and TypeScript.
You will learn how to:
- Use built-in device profiles
- Emulate iPhone and Android devices
- Configure custom viewports
- Test touch interactions
- Configure mobile user agents
- Test geolocation and permissions
- Perform responsive testing
- Build mobile login and e-commerce tests
- Use Page Object Model and fixtures
- Run tests across multiple devices
- Debug mobile failures
- Generate reports and traces
- Integrate mobile tests into CI/CD
Playwright provides a device registry with selected desktop, tablet, and mobile configurations. A device profile can configure characteristics such as viewport, screen size, user agent, and touch support.
What Is Playwright Mobile Emulation?
Playwright mobile emulation allows you to simulate selected mobile browser characteristics on your development machine or CI server.
Instead of connecting a physical smartphone, Playwright can configure a browser context with mobile-oriented settings.
Conceptually:
Desktop Computer
↓
Playwright
↓
Mobile Browser Configuration
↓
Viewport + User Agent + Touch + Device Settings
↓
For example:
import { test } from ‘@playwright/test’;
test(‘mobile homepage’, async ({ page }) => {
await page.goto(‘https://example.com’);
});
The test becomes mobile-oriented when the Playwright project uses a mobile device descriptor.
use: {
…devices[‘iPhone 12’]
}
Playwright’s emulation system can also configure geolocation, locale, timezone, permissions, and color scheme.
Mobile Emulation vs Real Mobile Device Testing
Mobile emulation is powerful, but it is not the same as testing on physical devices.
| Mobile emulation | Real-device testing |
| Runs on desktop infrastructure | Runs on physical hardware |
| Fast | Usually slower |
| Easy to automate | Requires device infrastructure |
| Excellent for responsive UI | Better for hardware behavior |
| Lower cost | Higher cost |
| Good for CI/CD | More complex CI/CD |
| Does not reproduce every hardware condition | Tests real device behavior |
Use emulation for
- Responsive layouts
- Mobile navigation
- Mobile forms
- Viewport testing
- Touch interactions
- User-agent-specific behavior
- Mobile browser automation
Use real devices for
- Hardware sensors
- Battery behavior
- Device-specific performance
- Camera integration
- Real network conditions
- OS-level behavior
- Physical-device compatibility
A mature Playwright Mobile Testing strategy can use emulation for broad automated coverage and real devices for targeted validation.
Why Use Mobile Emulation in Playwright?
Playwright mobile device emulation is useful because it allows teams to test mobile behavior without maintaining a physical device lab for every test.
Key benefits
- Fast execution
- Easy CI/CD integration
- Repeatable environments
- Built-in device profiles
- Multiple devices
- Responsive viewport testing
- Touch support
- Geolocation
- Permissions
- Cross-browser projects
It also integrates naturally with the Playwright Testing Framework.
Playwright Mobile Emulation Project Setup
Create a Playwright TypeScript project:
npm init playwright@latest
Choose:
TypeScript
tests
You can also install Playwright in an existing project:
npm install -D @playwright/test
A useful project structure is:
playwright-mobile/
│
├── tests/
│ ├── mobile-login.spec.ts
│ ├── mobile-products.spec.ts
│ └── mobile-checkout.spec.ts
│
├── pages/
│ ├── LoginPage.ts
│ ├── ProductPage.ts
│ └── CheckoutPage.ts
│
├── fixtures/
│ └── mobile.fixture.ts
│
├── playwright.config.ts
├── package.json
└── tsconfig.json
Playwright supports TypeScript directly, although its test runner does not perform full type checking; Playwright recommends running tsc –noEmit separately in CI.
Using Built-In Device Profiles
One of the easiest ways to start Playwright Device Emulation is to use a built-in device profile.
In playwright.config.ts:
import { defineConfig, devices } from ‘@playwright/test’;
export default defineConfig({
projects: [
{
name: ‘Mobile Chrome’,
use: {
…devices[‘Pixel 5’]
}
},
{
name: ‘Mobile Safari’,
use: {
…devices[‘iPhone 12’]
}
}
]
});
Then run:
npx playwright test
Playwright projects allow the same test suite to run against different browsers and device configurations.
To run only the iPhone project:
npx playwright test –project=”Mobile Safari
Playwright iPhone Emulation
A Playwright iPhone emulation test can use a predefined device profile.
import { test, expect } from ‘@playwright/test’;
test(‘iPhone homepage test’, async ({ page }) => {
await page.goto(‘https://example.com’);
await expect(
page.getByRole(‘heading’).first()
).toBeVisible();
});
Configuration:
import { defineConfig, devices } from ‘@playwright/test’;
export default defineConfig({
projects: [
{
name: ‘iPhone’,
use: {
…devices[‘iPhone 12’]
}
}
]
});
The device descriptor handles several mobile browser characteristics for you.
Playwright Android Emulation
You can similarly create a Playwright Android emulation project.
import { defineConfig, devices } from ‘@playwright/test’;
export default defineConfig({
projects: [
{
name: ‘Android’,
use: {
…devices[‘Pixel 5’]
}
}
]
});
Then:
npx playwright test –project=Android
This is useful for validating mobile layouts against a Chromium-based mobile configuration.
Custom Viewport and Screen Sizes
Sometimes a predefined device isn’t enough.
You can create a custom mobile viewport:
import { defineConfig } from ‘@playwright/test’;
export default defineConfig({
use: {
viewport: {
width: 390,
height: 844
}
}
});
Or override it for a particular test:
import { test } from ‘@playwright/test’;
test(‘custom mobile viewport’, async ({ page }) => {
await page.setViewportSize({
width: 390,
height: 844
});
await page.goto(‘/’);
// assertions
});
Viewport testing is useful for checking breakpoints such as:
320px
375px
390px
414px
768px
The goal isn’t to test every possible width. Select widths that represent your application’s important responsive breakpoints.
Device Scale Factor and Mobile Settings
A device configuration can include settings such as:
- Viewport
- Screen size
- Device scale factor
- User agent
- Touch support
Playwright’s device descriptors bundle selected mobile parameters so you don’t have to configure each one manually.
A custom configuration can look like:
use: {
viewport: {
width: 390,
height: 844
},
deviceScaleFactor: 3,
isMobile: true,
hasTouch: true
}
Use custom settings only when they represent a meaningful test requirement.
Touch Events and Mobile User Interactions
Mobile applications often use touch-oriented interactions.
Playwright allows touch support through hasTouch.
import { test, expect } from ‘@playwright/test’;
test.use({
hasTouch: true
});
test(‘mobile touch interaction’, async ({ page }) => {
await page.goto(‘/products’);
const button = page.getByRole(‘button’, {
name: ‘Add to Cart’
});
await button.tap();
await expect(
page.getByText(/added to cart/i)
).toBeVisible();
});
The hasTouch option specifies whether the viewport supports touch events.
Important
Don’t replace every click() with tap().
Use tap() when you specifically want to validate touch-oriented behavior.
User Agent and Mobile Browser Emulation
Some applications change behavior based on the user agent.
You can configure one explicitly:
import { test } from ‘@playwright/test’;
test.use({
userAgent:
‘Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 Chrome/120 Mobile Safari/537.36’
});
test(‘mobile user agent test’, async ({ page }) => {
await page.goto(‘/’);
// assertions
});
However, manually creating user-agent strings should generally be avoided when a built-in device descriptor already represents your intended environment.
A device descriptor gives you a more coherent configuration than changing only the user agent.
Geolocation and Permissions
Mobile websites sometimes depend on location.
Examples include:
- Food delivery
- Maps
- Ride booking
- Local shopping
- Weather
- Location-based promotions
Configure geolocation:
import { defineConfig } from ‘@playwright/test’;
export default defineConfig({
use: {
geolocation: {
latitude: 12.9716,
longitude: 77.5946
},
permissions: [‘geolocation’]
}
});
Playwright supports context-level geolocation and permissions.
Test:
import { test, expect } from ‘@playwright/test’;
test(‘location-based content’, async ({ page }) => {
await page.goto(‘/nearby’);
await expect(
page.getByText(/nearby stores/i)
).toBeVisible();
});
For production-quality tests, use non-sensitive test coordinates and avoid depending on unpredictable real-world location data.
Responsive Web Testing with Playwright
Responsive testing verifies that the UI adapts correctly to different screen dimensions.
Consider:
Desktop
↓
Tablet
↓
Mobile
A responsive test can validate:
- Navigation changes
- Mobile menu
- Column stacking
- Button sizing
- Text wrapping
- Product cards
- Images
- Forms
- Horizontal overflow
Example:
import { test, expect } from ‘@playwright/test’;
test(‘responsive navigation’, async ({ page }) => {
await page.goto(‘/’);
const menuButton = page.getByRole(‘button’, {
name: /menu/i
});
await expect(menuButton).toBeVisible();
await menuButton.click();
await expect(
page.getByRole(‘navigation’)
).toBeVisible();
});
This is more useful than simply checking that the browser window is small.
Real-World Mobile Login Example
A mobile login test might look like:
import { test, expect } from ‘@playwright/test’;
test(‘mobile user login’, async ({ page }) => {
await page.goto(‘/login’);
await page.getByLabel(‘Email’)
.fill(process.env.TEST_USERNAME!);
await page.getByLabel(‘Password’)
.fill(process.env.TEST_PASSWORD!);
await page.getByRole(‘button’, {
name: ‘Login’
}).tap();
await expect(page).toHaveURL(/dashboard/);
});
This validates both authentication and the mobile presentation of the login workflow.
Mobile Navigation, Menus, Forms, and Touch Interactions
A mobile e-commerce site may have a hamburger menu.
test(‘mobile navigation menu’, async ({ page }) => {
await page.goto(‘/’);
await page.getByRole(‘button’, {
name: /menu/i
}).tap();
await expect(
page.getByRole(‘navigation’)
).toBeVisible();
});
For a mobile form:
test(‘mobile checkout form’, async ({ page }) => {
await page.goto(‘/checkout’);
await page.getByLabel(‘First name’)
.fill(‘Test’);
await page.getByLabel(‘Last name’)
.fill(‘User’);
await page.getByLabel(‘Postal code’)
.fill(‘560001’);
await expect(
page.getByRole(‘button’, {
name: /place order/i
})
).toBeVisible();
});
Page Object Model for Mobile Tests
Mobile tests should use the same maintainable framework principles as desktop tests.
Create:
pages/MobileProductPage.ts
import { Page } from ‘@playwright/test’;
export class ProductPage {
constructor(private page: Page) {}
async open(productId: string) {
await this.page.goto(`/products/${productId}`);
}
async addToCart() {
await this.page.getByRole(‘button’, {
name: /add to cart/i
}).tap();
}
async openCart() {
await this.page.getByRole(‘link’, {
name: /cart/i
}).tap();
}
}
Test:
import { test, expect } from ‘@playwright/test’;
import { ProductPage } from ‘../pages/MobileProductPage’;
test(‘mobile product purchase flow’, async ({ page }) => {
const product = new ProductPage(page);
await product.open(‘1001’);
await product.addToCart();
await product.openCart();
await expect(
page.getByRole(‘heading’, {
name: /shopping cart/i
})
).toBeVisible();
});
The same Page Object can often support desktop and mobile if the underlying application behavior is the same.
Mobile Emulation with Fixtures and Test Projects
Playwright fixtures are useful for reusable mobile setup.
You can define projects:
import { defineConfig, devices } from ‘@playwright/test’;
export default defineConfig({
projects: [
{
name: ‘iPhone’,
use: {
…devices[‘iPhone 12’]
}
},
{
name: ‘Android’,
use: {
…devices[‘Pixel 5’]
}
}
]
});
Playwright projects are specifically designed to run the same tests using different configurations, including mobile devices.
You can also create custom fixtures when your mobile test suite requires reusable setup.
For example:
import { test as base } from ‘@playwright/test’;
export const test = base.extend({
mobileReady: async ({ page }, use) => {
await page.goto(‘/’);
await use(page);
}
});
Then:
test(‘mobile home page’, async ({
mobileReady
}) => {
// test mobile page
});
Screenshots, Videos, Trace Viewer, and Reporting
Mobile failures are often visual.
Configure failure artifacts:
import { defineConfig } from ‘@playwright/test’;
export default defineConfig({
use: {
screenshot: ‘only-on-failure’,
video: ‘retain-on-failure’,
trace: ‘retain-on-failure’
},
reporter: [
[‘html’],
[‘list’]
]
});
Run:
npx playwright test
Then:
npx playwright show-report
Trace Viewer can help identify:
- Incorrect viewport
- Wrong locator
- Mobile menu not opening
- Navigation failure
- Unexpected redirect
- Timing problems
- Application errors
For visual validation, you can also use:
await expect(page).toHaveScreenshot(‘mobile-home.png’, {
fullPage: true
});
This combines Playwright Mobile Testing with visual regression testing.
Cross-Device Testing and Parallel Execution
Create multiple projects:
projects: [
{
name: ‘iPhone’,
use: {
…devices[‘iPhone 12’]
}
},
{
name: ‘Android’,
use: {
…devices[‘Pixel 5’]
}
},
{
name: ‘Desktop’,
use: {
…devices[‘Desktop Chrome’]
}
}
]
Playwright can run projects concurrently subject to the configured worker limits.
Run everything:
npx playwright test
Run one device:
npx playwright test –project=iPhone
For large suites, parallel execution can significantly reduce total runtime.
However, tests must not share mutable state such as the same shopping cart or user account unless the test design intentionally handles it.
Playwright Mobile Emulation with CI/CD
Mobile tests should run automatically in CI.
Example GitHub Actions workflow:
name: Playwright Mobile Tests
on:
push:
branches: [main]
pull_request:
jobs:
mobile-tests:
runs-on: ubuntu-latest
steps:
– name: Checkout
uses: actions/checkout@v6
– name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: lts/*
– name: Install dependencies
run: npm ci
– name: Install Playwright browsers
run: npx playwright install –with-deps
– name: Type check
run: npx tsc –noEmit
– name: Run mobile tests
run: npx playwright test –project=iPhone
– name: Upload report
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v5
with:
name: playwright-mobile-report
path: playwright-report/
Playwright’s CI guidance recommends installing browser dependencies in the CI environment and supports collecting test reports as artifacts.
You can expand the workflow to Android:
npx playwright test –project=Android
or execute both projects in the same pipeline.
Real-World E-Commerce Playwright Mobile Automation Project
A strong portfolio project can be an E-Commerce Playwright Mobile Automation Project.
Recommended structure
ecommerce-mobile/
│
├── pages/
│ ├── LoginPage.ts
│ ├── HomePage.ts
│ ├── ProductPage.ts
│ ├── CartPage.ts
│ └── CheckoutPage.ts
│
├── tests/
│ ├── mobile-login.spec.ts
│ ├── mobile-products.spec.ts
│ ├── mobile-cart.spec.ts
│ └── mobile-checkout.spec.ts
│
├── fixtures/
│ └── mobile.fixture.ts
│
├── playwright.config.ts
└── package.json
Test 1: Mobile login
Validate:
- Login form
- Mobile keyboard behavior
- Login button
- Error messages
- Redirect to dashboard
Test 2: Product listing
Validate:
- Product cards
- Responsive layout
- Product images
- Category filters
- Search
Test 3: Product details
Validate:
- Product information
- Price
- Image
- Add-to-cart button
- Touch interaction
Test 4: Shopping cart
Validate:
- Cart item
- Quantity
- Price
- Remove action
- Total
Test 5: Checkout
Validate:
- Address form
- Shipping options
- Payment fields
- Order summary
- Confirmation
Test 6: Multiple devices
Run:
iPhone
Android
Desktop
Test 7: Screenshots
Capture important screens:
await expect(page).toHaveScreenshot(
‘mobile-product.png’
);
Test 8: Debugging
Collect:
Screenshots
Videos
Traces
Test 9: CI/CD
Run the complete project through GitHub Actions.
This portfolio project demonstrates:
Playwright + TypeScript + Mobile Emulation + Responsive Testing + POM + Fixtures + Visual Testing + CI/CD + Reporting.
Common Playwright Mobile Emulation Errors and Solutions
| Problem | Cause | Solution |
| Desktop layout appears | Mobile project not selected | Check –project |
| Mobile menu missing | Incorrect breakpoint | Verify viewport |
| Touch test fails | Touch not enabled | Use device profile or hasTouch |
| Geolocation denied | Permission missing | Add permissions: [‘geolocation’] |
| Wrong responsive layout | Incorrect viewport | Check width/height |
| User-agent behavior wrong | Custom UA mismatch | Prefer device descriptors |
| Screenshot mismatch | Different environment | Standardize browser/OS |
| CI mobile test fails | Browser dependency issue | Run playwright install –with-deps |
| Test is flaky | Shared state/timing | Isolate data and use assertions |
| Element is off-screen | Responsive layout | Use locator-based interactions |
Playwright Mobile Testing Best Practices
Follow these practices for reliable mobile automation.
1. Prefer built-in device profiles
Start with:
devices[‘iPhone 12’]
or:
devices[‘Pixel 5’]
before creating custom settings.
2. Test important breakpoints
Don’t test hundreds of viewport sizes.
Focus on business-critical responsive breakpoints.
3. Test behavior, not just dimensions
Check:
- Navigation
- Forms
- Buttons
- Menus
- Product cards
- Checkout
4. Use accessible locators
Prefer:
page.getByRole(‘button’)
over brittle CSS selectors.
5. Use Page Object Model
Keep mobile interaction logic reusable.
6. Isolate test data
Avoid shared carts and accounts.
7. Use screenshots strategically
Visual testing is valuable for important mobile layouts.
8. Capture traces on failures
This makes CI failures easier to investigate.
9. Use CI for regression testing
Run mobile projects on every important pull request.
10. Don’t treat emulation as a replacement for real devices
Use physical devices when hardware-specific behavior matters.
Playwright Mobile Emulation Interview Questions with Answers
1. What is Playwright mobile emulation?
It is the process of configuring Playwright to simulate selected mobile browser characteristics such as viewport, user agent, screen size, and touch support.
2. How do I use mobile emulation in Playwright?
Use a built-in device descriptor:
use: {
…devices[‘iPhone 12’]
}
3. What is a Playwright device profile?
A device profile is a predefined set of browser-context settings representing a selected device configuration.
4. Can Playwright emulate an iPhone?
Yes. Playwright includes selected mobile device descriptors such as iPhone profiles.
5. Can Playwright emulate Android?
Yes. You can use an Android-oriented device profile such as Pixel 5.
6. What is hasTouch?
hasTouch indicates whether the emulated viewport supports touch events.
hasTouch: true
7. Can Playwright test geolocation?
Yes.
geolocation: {
latitude: 12.9716,
longitude: 77.5946
},
permissions: [‘geolocation’]
8. Is Playwright mobile emulation the same as real-device testing?
No. Emulation reproduces browser/device characteristics but does not reproduce every hardware and operating-system condition of a physical device.
9. How do you test multiple mobile devices?
Create multiple Playwright projects using different device descriptors.
10. How do you debug mobile test failures?
Use:
Screenshots
Videos
Trace Viewer
Console logs
Then check the viewport, device configuration, locators, application state, and test data.
Learning Roadmap for Beginners
If you are new to Playwright Mobile Emulation, follow this sequence.
Step 1: Learn Playwright basics
Understand:
- Locators
- Assertions
- Browser
- Context
- Page
- Auto-waiting
Step 2: Learn Playwright TypeScript
Practice:
- Classes
- Interfaces
- Async/await
- Modules
- Types
Step 3: Learn device profiles
Start with:
iPhone
Android
Tablet
Step 4: Learn responsive testing
Practice different:
Viewport widths
Navigation layouts
Forms
Product cards
Step 5: Learn mobile interactions
Practice:
tap()
Touch support
Mobile menus
Scrolling
Step 6: Learn advanced emulation
Study:
- User agent
- Geolocation
- Permissions
- Locale
- Timezone
- Color scheme
Step 7: Learn framework architecture
Add:
- Page Object Model
- Fixtures
- Test data
- Authentication
- Visual testing
Step 8: Learn CI/CD
Practice:
- GitHub Actions
- Docker
- Reports
- Traces
- Parallel execution
Step 9: Build the e-commerce project
Publish a sanitized version on GitHub.
This gives you a portfolio project demonstrating real-world Playwright Responsive Testing and mobile automation skills.
FAQs: Playwright Mobile Emulation Tutorial
What is Playwright mobile emulation?
Playwright mobile emulation simulates selected mobile browser characteristics such as viewport, screen size, user agent, and touch support.
How do I use mobile emulation in Playwright?
Configure a device project:
projects: [
{
name: ‘iPhone’,
use: {
…devices[‘iPhone 12’]
}
}
]
Does Playwright support iPhone emulation?
Yes. Playwright provides selected iPhone device descriptors.
Does Playwright support Android emulation?
Yes. Android-oriented device profiles are available through Playwright’s device registry.
Can Playwright emulate touch?
Yes. Device profiles can enable touch support, and you can configure hasTouch explicitly.
Can Playwright emulate GPS?
Yes. Use geolocation and grant the appropriate permission.
Is mobile emulation enough for mobile testing?
It is excellent for automated responsive and browser-level testing, but real devices remain important for hardware- and OS-specific validation.
Can Playwright mobile tests run in CI/CD?
Yes. Mobile device projects can run in CI just like other Playwright projects.
Can I perform visual testing on mobile?
Yes. You can combine mobile device projects with Playwright screenshot assertions.
