How to Screenshot a Website at an Android Tablet Viewport in Puppeteer
Set a target tablet viewport before navigation, then capture it with Puppeteer. Learn when to use device emulation, full-page capture, and how to troubleshoot common issues.
To screenshot a website at an Android tablet viewport in Puppeteer, set the page viewport before navigation, then call page.screenshot(). Choose the width and height your project targets; Android tablets do not share one universal viewport. If you need the selected device’s user agent as well as its dimensions, use Puppeteer’s device emulation.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.setViewport({
width: 800,
height: 1280,
deviceScaleFactor: 1,
});
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.screenshot({ path: 'tablet-viewport.png' });
} finally {
await browser.close();
}
The 800 × 1280 dimensions above are illustrative inputs, not a standard Android tablet profile. Replace them with dimensions specified by your test or product requirements. See Puppeteer’s setViewport documentation and screenshots guide.
1. Choose what you mean by an Android tablet viewport
A viewport is the page’s CSS-pixel width and height. Set those dimensions explicitly for a controlled responsive-layout check. The viewport alone does not make the browser identical to a physical Android tablet.
If your test also needs a tablet user agent and device metrics, emulate a named device. Puppeteer describes page.emulate(device) as a shortcut for setting both the user agent and viewport. Device emulation still does not establish pixel-perfect equivalence to physical hardware, its operating system, or its browser version.
| Approach | Use it when | What it configures |
|---|---|---|
page.setViewport() |
You need specific dimensions or a project-defined test size. | Viewport width, height, and device scale factor, plus optional viewport properties. |
page.emulate(device) |
You want a Puppeteer device profile. | The device’s user agent and viewport settings. |
Choose the dimensions or device profile intentionally and record that choice in the test. Do not label an arbitrary width and height as a universal Android tablet size.
2. Capture a chosen viewport with Puppeteer
Install Puppeteer in your project using its official installation instructions, then save this as an ES module, for example screenshot.mjs. Run it with node screenshot.mjs.
import puppeteer from 'puppeteer';
const targetUrl = process.argv[2] ?? 'https://example.com';
const outputPath = process.argv[3] ?? 'tablet-viewport.png';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
// Set the project's target CSS-pixel dimensions before navigating.
await page.setViewport({
width: 800,
height: 1280,
deviceScaleFactor: 1,
});
await page.goto(targetUrl, { waitUntil: 'networkidle2' });
await page.screenshot({ path: outputPath });
console.log(`Saved ${outputPath}`);
} finally {
await browser.close();
}
Example: node screenshot.mjs https://example.com tablet.png. The viewport is configured before goto(), so the page loads at the intended dimensions. Puppeteer cautions that changing viewport settings can affect page behavior; changes to isMobile or hasTouch can cause a reload in some cases. See Page.setViewport().
Set device pixel density deliberately
deviceScaleFactor controls the emulated device pixel ratio. A value of 1 is suitable when you want the screenshot’s pixel dimensions to correspond directly to the configured CSS viewport dimensions. A larger value produces a denser raster image. Set it to the value your project needs and verify the resulting image dimensions; do not assume viewport CSS pixels and output bitmap pixels are always the same.
3. Emulate a named device when the user agent matters
Use Puppeteer’s device descriptors when your test requires the profile’s user agent and viewport together. Descriptor names and availability depend on the installed Puppeteer version, so inspect the descriptors provided by that version rather than copying a device name blindly.
import puppeteer from 'puppeteer';
import { KnownDevices } from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
const device = KnownDevices['iPad'];
if (!device) {
throw new Error('Requested device descriptor is not available');
}
await page.emulate(device);
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.screenshot({ path: 'emulated-device.png' });
} finally {
await browser.close();
}
This demonstrates the API shape with a named descriptor; it is not an Android tablet profile. Select an Android tablet descriptor only if one exists in the installed Puppeteer version and matches your test requirement. Otherwise use setViewport() for dimensions and configure any needed user agent separately. Puppeteer’s emulate method and KnownDevices reference describe the available device emulation APIs.
4. Capture the visible viewport or the full page
By default, page.screenshot() captures the visible page viewport. Keep fullPage unset or set it to false when the artifact should show only the configured screen. Use fullPage: true when you want content beyond the viewport included.
// Visible viewport
await page.screenshot({ path: 'viewport.png' });
// Entire page, extending beyond the viewport
await page.screenshot({ path: 'full-page.png', fullPage: true });
Screenshot options also include controls such as clip for a defined region and captureBeyondViewport. Use a clip when you need a particular rectangle; ensure its coordinates and dimensions fit the content you intend to capture. See the official ScreenshotOptions reference.
5. Make capture timing reliable
The sample waits for networkidle2 before capture. Pages with ongoing network activity, analytics, or long-running requests may not reach that condition promptly. Conversely, a navigation event does not guarantee that every image, animation, or client-rendered element is ready for your use case.
- Choose a navigation wait condition that matches the page; Puppeteer’s Page.goto() documents the supported options.
- For a known page element, wait for that selector before capturing with
page.waitForSelector(). - For content that appears after a known application action, perform that action and wait for a meaningful page condition instead of relying on an arbitrary delay.
- For animated or frequently changing content, stabilize the page state before capture if your test requires repeatable output.
6. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| The page has desktop layout or the wrong responsive breakpoint. | The viewport was set after navigation, or the configured dimensions do not match the intended test. | Set the viewport before goto(); confirm the target CSS-pixel width and height. |
| The output image dimensions differ from the CSS viewport. | deviceScaleFactor changes raster density. |
Set the intended scale factor explicitly and check the saved image’s pixel dimensions. |
| The site behaves differently from a tablet. | Viewport sizing changes page dimensions but does not alone supply a tablet user agent or reproduce physical hardware. | Use a matching Puppeteer device descriptor when available, or configure the required user agent and viewport separately. Validate hardware-specific behavior on the target device. |
| Capture hangs or times out waiting for navigation. | The page may keep network requests active or fail to reach the selected wait condition. | Choose a navigation wait condition suited to the site, then wait for the specific content needed for the screenshot. |
| The screenshot cuts off content below the fold. | The default screenshot is viewport-sized. | Use fullPage: true for a full-page image, or retain the default for a viewport capture. |
| Changing mobile or touch settings reloads the page. | Puppeteer notes that changing isMobile or hasTouch can cause a reload in some cases. |
Configure those settings before navigation, then wait for the page to settle before capturing. |
| The named device lookup is undefined. | The descriptor name is unavailable or differs in the installed Puppeteer version. | Inspect that version’s KnownDevices entries and select an available descriptor; use a manual viewport if none fits. |
7. Performance, reliability, and cost
Screenshot work consumes browser startup, page loading, rendering, and image encoding time. Reuse a browser process for batches of independent captures when appropriate, while creating a separate page per task and closing pages when finished. Always close the browser in a finally block so failed navigations do not leave a process running.
Use a bounded timeout strategy in production and handle navigation and capture errors explicitly. Sites can change content, block automation, or depend on external resources, so a successful screenshot is not proof that a responsive layout is correct on physical Android hardware. Keep the viewport, scale factor, URL, and relevant browser version with test results to make differences easier to diagnose.
With a self-hosted Puppeteer workflow, account for the compute and maintenance of the browser environment. The supplied Puppeteer references do not specify a universal runtime or cost figure; both depend on the site, infrastructure, and workload.
8. Or skip the browser setup
If you need a screenshot without managing Puppeteer, ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request returns an image or PDF. Its API supports custom viewports and device presets; consult the ScreenshotNeo documentation for the current parameter names and request options.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com \
-o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.com',
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(({ writeFile }) =>
writeFile('shot.webp', Buffer.from(await res.arrayBuffer()))
);
Pass your target tablet viewport using the documented viewport parameters. ScreenshotNeo removes cookie banners, popups, and chat widgets before the shot; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Sign up for free and get 1,000 screenshots a month with no card.
9. Frequently asked questions
Is 800 × 1280 the standard Android tablet viewport?
No. It is an illustrative configuration. Use the dimensions required by the device or responsive test you are targeting.
Does setting a tablet viewport prove the site works on Android hardware?
No. It configures a browser test. Hardware, operating system, browser version, and device-specific behavior can differ.
Should I use fullPage: true for a tablet screenshot?
Only when you need the entire document. Leave it off for an image of the visible tablet viewport.
Can I use this for responsive regression tests?
Yes. Keep the viewport dimensions and scale factor consistent across runs, and compare screenshots under the same browser and page state.


