How to Capture a Screenshot of a Website with Selenium Using a Proxy
Configure a proxy in Selenium 4, wait for the page content you need, and save a screenshot. Includes Python code, options, troubleshooting, and a no-browser alternative.
To capture a website screenshot with Selenium through a proxy, configure the proxy on the browser options before creating the WebDriver, navigate to the page, wait for the content that matters, then save the screenshot. In Selenium 4 with Python, options.proxy accepts a Proxy configured with ProxyType.MANUAL. The example below configures an HTTP proxy endpoint; use your provider’s instructions for HTTPS routing, authentication, and certificates.
Complete Python example
Install Selenium in the Python environment that will run the script:
python -m pip install selenium
Save this as capture.py. Replace the URL and proxy host and port with values you are authorized to use.
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.proxy import Proxy, ProxyType
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
TARGET_URL = "https://example.com"
PROXY_ENDPOINT = "proxy.example:8080"
OUTPUT_PATH = Path("screenshot.png").resolve()
options = webdriver.ChromeOptions()
options.proxy = Proxy({
"proxyType": ProxyType.MANUAL,
"httpProxy": PROXY_ENDPOINT,
})
# Optional: set the initial browser viewport. This controls the visible window capture.
options.add_argument("--window-size=1440,1000")
driver = webdriver.Chrome(options=options)
try:
driver.get(TARGET_URL)
# Wait for content that signals the page is ready for your capture.
WebDriverWait(driver, 20).until(
EC.visibility_of_element_located((By.TAG_NAME, "h1"))
)
saved = driver.save_screenshot(str(OUTPUT_PATH))
if not saved:
raise OSError(f"WebDriver could not save screenshot to {OUTPUT_PATH}")
print(f"Saved {OUTPUT_PATH}")
finally:
driver.quit()
For a site without an h1, replace the wait with a condition that reflects the content you need, such as a known CSS selector becoming visible or a loading indicator disappearing. If the page is static, you can omit the explicit wait, though a meaningful wait is more reliable for dynamic sites.
How the proxy setting works
A proxy acts as an intermediary for requests between a client and a server. Selenium applies browser configuration through an Options object when it creates a session. In the example, ProxyType.MANUAL selects a manually configured proxy and httpProxy supplies its host and port. Selenium documents other proxy configuration modes, including direct and PAC configurations; choose the mode and fields required by your environment.
| Setting or choice | When it matters |
|---|---|
ProxyType.MANUAL |
Use when you have a specific proxy endpoint to configure. |
httpProxy |
Provides an HTTP proxy host and port in the documented Python example. Do not assume this alone handles every provider’s HTTPS traffic. |
| Direct or PAC mode | Use when your network setup calls for direct connections or a proxy auto-configuration file. Follow the relevant Selenium and provider configuration instructions. |
| Provider authentication and certificates | These are provider and environment specific. Consult current provider guidance; the generic example does not establish a universal credential or certificate syntax. |
| Local browser or Remote WebDriver | For a Grid session, pass the browser Options instance to Remote WebDriver so the requested browser and its settings are part of the session. |
To bypass proxy settings when you need a direct connection, use a Proxy instance configured with ProxyType.DIRECT. Selenium’s Chrome Options API deprecates ignore_local_proxy_environment_variables() and recommends using a Proxy instance with direct mode instead.
Wait for the page state you want to capture
driver.get() follows the browser’s page-load strategy. The default waits for the document ready state to become complete, but that does not guarantee that a single-page app has fetched data, finished rendering, or removed its loading overlay. Wait for a condition tied to the screenshot’s purpose.
Wait for a target element
WebDriverWait(driver, 20).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, "main .report"))
)
Wait for a loading indicator to disappear
WebDriverWait(driver, 20).until(
EC.invisibility_of_element_located((By.CSS_SELECTOR, ".loading-spinner"))
)
Use a timeout appropriate for the page and your environment. Avoid making a fixed sleep the default: it can waste time on fast responses and still be too short when a response is slow. If you need a delay for a known animation or scheduled content, make it an explicit, documented choice.
Choose the screenshot scope
driver.save_screenshot(path) saves the current browser window screenshot as a PNG. It captures the current view; it is not necessarily a full-page image. The method returns a boolean, so checking the result can catch a file-writing failure.
Capture a specific element
report = driver.find_element(By.CSS_SELECTOR, "main .report")
if not report.screenshot("report.png"):
raise OSError("Could not save element screenshot")
Element screenshots are useful when the intended artifact is one component, chart, or report rather than the visible page. Make sure the element has rendered and is in a capturable state before saving.
Save to an explicit path
Use an absolute path when the process working directory might differ from the directory you expect. The Python API recommends a full path; the example resolves one with Path.resolve(). Ensure the parent directory exists and that the process can write there.
Chrome, driver, and remote session setup
Modern Selenium includes Selenium Manager to handle browser and driver setup in supported cases. If you manage ChromeDriver yourself, Selenium’s Chrome documentation says the Chrome and ChromeDriver major versions must match. Selenium 4’s Chrome documentation covers Chrome v75 and later.
For a remote Selenium Grid, configure the same browser Options object and provide it to Remote WebDriver. The Grid endpoint and authentication depend on your deployment:
from selenium import webdriver
options = webdriver.ChromeOptions()
# Configure options.proxy here as in the local example.
driver = webdriver.Remote(
command_executor="https://grid.example/wd/hub",
options=options,
)
Replace the illustrative Grid endpoint with the endpoint supplied by your environment. Confirm that the Grid browser can reach the proxy endpoint; configuring a proxy on the browser does not make an unreachable network route available.
Reliability, performance, and cost considerations
- Always close the session. Put
driver.quit()in afinallyblock so the browser is closed after navigation, waiting, or file errors. - Wait for the right condition. A page-specific wait avoids capturing an incomplete app after document navigation has finished.
- Keep proxy behavior explicit. A proxy adds a network dependency. Check connectivity and provider rules if the browser cannot load the target or some resources fail.
- Limit capture scope when possible. An element screenshot can avoid producing a larger artifact than the task needs. Viewport size also affects the current-window image dimensions.
- Plan for resource cleanup in batch work. Reuse a session only when its proxy, cookies, and browser state are appropriate for the next capture; otherwise isolate sessions and still quit them reliably.
- Account for infrastructure costs. Selenium itself does not specify a universal proxy price or runtime cost. Those depend on your browser hosting, Grid, proxy provider, traffic, and usage plan. No general performance benchmark or proxy success rate is established here.
Troubleshooting
| Symptom | Likely cause | What to check or change |
|---|---|---|
| Browser cannot reach the page | Proxy host or port is wrong, unavailable, or unreachable from the browser environment. | Check the endpoint and network route from the machine or Grid node running Chrome. Confirm provider settings. |
| HTTPS page fails through the proxy | The configured HTTP proxy field may not match the provider’s HTTPS routing requirements. | Use the provider’s current Selenium/browser instructions for HTTPS support, authentication, and certificates. |
| Proxy authentication fails | The generic manual proxy example does not define a universal authentication method. | Follow your provider’s documented browser configuration. Do not assume adding credentials to the endpoint URL is supported or safe. |
| Screenshot is blank or missing dynamic content | The document reached ready state before the application rendered the desired content. | Wait for a visible target element or for the loading state to disappear, and confirm the target is not inside a frame you have not selected. |
| Wait raises a timeout | The selector does not match, the element never becomes visible, or the page failed to load. | Verify the selector and page state, inspect navigation errors, and set a timeout that fits expected response conditions. |
save_screenshot returns false or raises an I/O error |
The path may be unwritable, invalid, or relative to an unexpected working directory. | Use an absolute path, ensure the directory exists, and check process permissions and available storage. |
| Chrome session fails to start | Chrome and ChromeDriver may be incompatible, or browser installation is unavailable. | Use Selenium Manager where supported, or align the Chrome and ChromeDriver major versions. |
| Remote session ignores the intended browser settings | Options were not passed to Remote WebDriver, or the Grid uses a different browser configuration. | Pass the Options instance to the remote session and verify the Grid’s browser and network configuration. |
Or skip the browser setup
If you need a website capture without provisioning Selenium and a proxy, ScreenshotNeo provides a screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation for the 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,
)
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}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account.
FAQ
How do I take a screenshot with Selenium and a proxy?
Set the proxy on browser Options before driver creation, navigate, wait for the content you need, save the screenshot, and quit the driver. The Python example above shows the complete sequence.
How do I set a proxy in Selenium Python?
Use webdriver.ChromeOptions() and assign a Selenium Proxy with the required proxy type and endpoint to options.proxy, then pass options to webdriver.Chrome.
Does Selenium save a full-page screenshot?
save_screenshot captures the current browser window. Use an element’s screenshot method for a specific element. Full-page capture behavior is browser and implementation dependent and is not provided by the basic method shown here.
Can I use a proxy with Selenium Grid?
Yes. Provide the configured browser Options to Remote WebDriver, and ensure the Grid node can reach the proxy. The Grid’s endpoint and network rules depend on its operator.


