How to Take a Screenshot of a Mobile Webpage with Selenium Chrome Emulation
Emulate a mobile device in Chrome, wait for the page content you need, and save a screenshot with Selenium in Python.
To screenshot a mobile webpage with Selenium and Chrome, enable Chrome’s mobile emulation when creating the WebDriver session, open the page, wait for the content you want to capture, then save the current browser window as a PNG. Setting only the window size is not equivalent to mobile emulation: mobile emulation also changes device metrics and mobile-related browser behavior.
1. Install Selenium and prepare Chrome
Install Selenium for Python and make sure Chrome is available in the environment where the script runs:
python -m pip install selenium
Recent Selenium versions can manage the matching ChromeDriver automatically when it is available to the environment. In restricted or pinned environments, install and configure a ChromeDriver compatible with the installed Chrome version. Run the script where a browser can start; a headless server may require additional environment-specific setup.
2. Configure mobile emulation and capture the page
This complete example uses custom device metrics. The dimensions and pixel ratio are illustrative viewport settings, not a claim that they represent a particular current phone. Replace them with the dimensions used by your test. The mobileEmulation capability must be set before the driver session is created.
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
url = "https://example.com"
options = Options()
options.add_experimental_option("mobileEmulation", {
"deviceMetrics": {
"width": 360,
"height": 640,
"pixelRatio": 3.0,
}
})
# Optional in environments that support Chrome's headless mode:
# options.add_argument("--headless=new")
driver = webdriver.Chrome(options=options)
try:
driver.get(url)
WebDriverWait(driver, 20).until(
lambda d: d.execute_script("return document.readyState") == "complete"
)
driver.save_screenshot("mobile-page.png")
finally:
driver.quit()
Remove the one leading space before driver = in the code if your editor treats it as an unexpected indent; the line should align with options =. A corrected aligned line is shown below:
driver = webdriver.Chrome(options=options)
The document-ready check confirms that the browser reports the initial document as complete. It does not guarantee that client-rendered content, images, ads, or data loaded later are ready. Prefer an explicit wait for the page state or element that should be visible in the screenshot:
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
WebDriverWait(driver, 20).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, "main .article-title"))
)
driver.save_screenshot("mobile-page.png")
Use a selector that is meaningful for the page under test. If the content is updated after the element appears, wait for the relevant text or state to change as well. Always call quit() in a finally block so Chrome and the driver process are closed even when navigation or capture raises an error.
3. Choose a device profile or custom metrics
| Configuration | Use it when | Trade-off |
|---|---|---|
| Named device profile | You want one of Chrome’s available emulated profiles. | Profile availability can depend on the Chrome version in use. |
| Custom device metrics | You know the viewport width, height, and pixel ratio your test requires. | You must supply and maintain those values yourself. |
For a named profile, provide the profile name supported by the Chrome version in the environment. Verify that name against that version rather than assuming every profile is available everywhere:
options.add_experimental_option("mobileEmulation", {
"deviceName": "SUPPORTED_DEVICE_PROFILE"
})
For custom metrics, use the deviceMetrics object shown in the runnable example. A mobile user-agent string can also be supplied when your test specifically needs one, but user-agent changes alone do not configure viewport metrics or all mobile behavior:
options.add_experimental_option("mobileEmulation", {
"deviceMetrics": {"width": 360, "height": 640, "pixelRatio": 3.0},
"userAgent": "YOUR_MOBILE_USER_AGENT"
})
Use a user-agent value appropriate to the test and browser version. The exact user-agent behavior depends on Chrome and the configuration. Emulation is useful for responsive layout checks, but it is not a guarantee of identical rendering or behavior on a physical phone. If operating-system, hardware, browser, or network differences matter, include validation on an actual device.
4. Understand what Selenium saves
driver.save_screenshot("mobile-page.png") saves a PNG screenshot of the current browser window. You can also get the PNG bytes in memory or save them through a file-like workflow:
png_bytes = driver.get_screenshot_as_png()
with open("mobile-page.png", "wb") as image_file:
image_file.write(png_bytes)
This is a current-window capture. Do not describe it as a full-page screenshot: a long page may extend below the viewport and will not automatically be represented in full by this method. If the deliverable must contain the whole document, use a separately verified full-page technique and check its behavior for your Chrome and Selenium versions.
5. Capture reliably in scripts and CI
- Keep the device configuration fixed for comparable runs; record viewport width, height, pixel ratio, Chrome version, and relevant browser flags with the test output.
- Wait for the element or application state that matters, not just a short fixed sleep. Use a timeout that allows for expected slow responses, and fail clearly if the expected state never appears.
- Use stable selectors and capture after animations or transitions have settled if they affect the image.
- Write screenshots to a known directory, and create that directory before saving when needed.
- Run
driver.quit()in cleanup code so failed runs do not leave browser processes behind. - For CI, make Chrome and its driver available in the runner, choose headless mode only where supported, and avoid relying on a developer’s local browser state.
Large device pixel ratios and viewport dimensions can increase screenshot pixel dimensions and memory use. Keep the capture size close to the target test case. Selenium does not provide a cost per screenshot in the cited API documentation; resource cost in this workflow comes from running the browser and any test infrastructure around it.
6. Troubleshoot common problems
| Symptom | Likely cause | Fix |
|---|---|---|
| ChromeDriver or session creation fails | The driver cannot start Chrome, or the browser and driver setup is incompatible. | Check that Chrome is installed and runnable in the execution environment. Use a compatible driver setup and inspect the session error for the specific failure. |
mobileEmulation is ignored or rejected |
The capability was added after driver creation, the option structure is malformed, or the profile name is unsupported. | Set the experimental option before webdriver.Chrome(...). Check spelling and use either a supported deviceName or valid custom metrics. |
| The result looks like desktop layout | Only the window was resized, or emulation was not enabled on the session. | Configure mobileEmulation as a Chrome session option. Confirm the page responds to the emulated viewport and mobile settings. |
| Screenshot is blank or missing page content | The page or client-rendered content was not ready when capture ran. | Wait for the specific visible element, text, or application state needed for the image. Check whether the page displays an error or requires authentication. |
| Screenshot is only the visible portion | The current-window screenshot method captures the browser window, not automatically the entire document. | Use a verified full-page capture approach if the task requires the entire document. |
| Screenshot file is not where expected | The script uses a different working directory, or the destination directory does not exist. | Save to an absolute path or create the destination directory first; check the boolean result from save_screenshot. |
| Capture times out intermittently | The readiness condition is too strict or the page is slow or inconsistent. | Wait for the smallest meaningful page condition, set a suitable timeout, and report which condition timed out. Do not hide intermittent failures with an arbitrary sleep. |
7. When local emulation is not enough
Chrome emulation is suitable for repeatable viewport-oriented checks. For a screenshot without managing a local browser session, ScreenshotNeo provides a website screenshot API and MCP server. Its API accepts a URL and returns an image or PDF; the service also supports mobile device presets and custom viewports. See the ScreenshotNeo API documentation for parameters and response details.
Or skip the browser setup
Make one request with your API key and target URL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', new Uint8Array(await res.arrayBuffer()));
Replace the example URL with the page you want to capture. The API can emulate mobile viewports. Cookie and consent banners are accepted and removed before capture, along with supported newsletter popups and chat widgets. Bot checks, blank pages, failed loads, and cache hits are not billed; response headers report the page verdict and billing status. An MCP server provides screenshot tools for AI agents, including Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is available on every plan.
Sign up for 1,000 free screenshots a month, with no card required.
FAQ
Does changing Chrome’s window size enable mobile emulation?
No. Window sizing alone does not apply all device metrics and mobile browser behavior. Configure mobile emulation before creating the session.
Can Selenium save the screenshot as JPEG?
The documented Python screenshot methods save or return PNG data. Convert the image after capture if another format is required.
Does this prove the page works on every phone?
No. It captures an emulated Chrome state. Use an actual device as an additional check when physical-device differences matter.
Will a long webpage fit in the screenshot?
Not with the current-window screenshot call alone. It captures the current window; use a verified full-page method if the entire document is required.


