How to Run Selenium with Chrome in Python
Install Selenium, launch Chrome, interact with a page, wait for dynamic content, and clean up reliably—with troubleshooting tips and a screenshot API option.
To run Selenium with Chrome in Python, install Selenium in the Python environment that will run your script, then create a session with webdriver.Chrome(). In current Selenium versions, Selenium Manager can find or obtain a compatible driver when one is not already configured, so most local setups do not need a manually downloaded ChromeDriver.
1. Install Selenium in a project environment
A virtual environment keeps this project’s dependencies separate from system Python and other projects. Run these commands from your project directory:
python -m venv .venv
# macOS or Linux:
source .venv/bin/activate
# Windows PowerShell:
# .\.venv\Scripts\Activate.ps1
python -m pip install -U selenium
Use python -m pip so pip installs into the interpreter selected by python. On systems where the Python 3 command is python3, use it consistently for both environment creation and installation. Selenium’s official Python documentation recommends a virtual environment and documents pip install -U selenium as the install or update command: Selenium Python installation.
Chrome must also be installed and launchable on the machine. Selenium 4 includes Selenium Manager, shipped with Selenium releases starting at 4.6, to assist with driver management when a driver is unavailable. See the Selenium Manager documentation.
2. Run a complete first script
Save this as selenium_chrome.py and run python selenium_chrome.py. It opens Selenium’s demonstration form, enters text, submits it, prints the result, and closes the browser even if an operation raises an exception.
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
try:
driver.get("https://www.selenium.dev/selenium/web/web-form.html")
print("Page title:", driver.title)
text_box = driver.find_element(By.NAME, "my-text")
submit_button = driver.find_element(By.CSS_SELECTOR, "button")
text_box.send_keys("Selenium")
submit_button.click()
message = driver.find_element(By.ID, "message")
print("Form result:", message.text)
finally:
driver.quit()
The core WebDriver flow is navigation with get(), locating elements, interacting with them, and reading page state. The locators above use a name, CSS selector, and ID. Selenium’s official first Python script demonstrates this same form and interaction pattern.
3. Wait for dynamic pages explicitly
Modern pages often render or update content after the initial navigation. Selenium’s documentation calls synchronization with browser state one of the biggest challenges in WebDriver automation, and notes that the implicit wait in its introductory example is only a placeholder. Prefer an explicit wait for the condition your next step requires.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
driver = webdriver.Chrome()
try:
driver.get("https://www.selenium.dev/selenium/web/web-form.html")
wait = WebDriverWait(driver, 10)
text_box = wait.until(
EC.visibility_of_element_located((By.NAME, "my-text"))
)
text_box.send_keys("Selenium")
submit = wait.until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "button"))
)
submit.click()
message = wait.until(
EC.visibility_of_element_located((By.ID, "message"))
)
print(message.text)
finally:
driver.quit()
WebDriverWait polls for a condition until it succeeds or the timeout expires. Choose a condition that matches the operation: visibility before reading or typing, clickability before clicking, and presence when only DOM existence matters. Avoid combining implicit and explicit waits without understanding the resulting timing behavior; prefer one deliberate wait strategy.
4. Common browser operations
Choose a locator
Use stable page attributes when available. Selenium’s By supports ID, name, class name, tag name, link text, partial link text, CSS selector, and XPath. CSS selectors are useful for scoped relationships; XPath can express relationships that are awkward in CSS. Avoid brittle selectors tied to generated class names or a page’s incidental layout.
from selenium.webdriver.common.by import By
by_id = driver.find_element(By.ID, "email")
by_name = driver.find_element(By.NAME, "q")
by_css = driver.find_element(By.CSS_SELECTOR, "form input[type='email']")
by_xpath = driver.find_element(By.XPATH, "//button[normalize-space()='Submit']")
Read and change browser state
driver.get("https://example.com")
print(driver.title)
print(driver.current_url)
heading = driver.find_element(By.CSS_SELECTOR, "h1")
print(heading.text)
search = driver.find_element(By.NAME, "q")
search.clear()
search.send_keys("browser automation")
Replace example URLs and selectors with ones from the site you are authorized to automate. A locator that matches no element raises NoSuchElementException; on dynamic pages, wait for the appropriate condition before locating or acting.
5. Configure Chrome when needed
For ordinary desktop use, start with the default webdriver.Chrome(). Chrome options and a service path are useful when the environment requires specific browser arguments or an explicitly managed driver.
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--headless")
options.add_argument("--window-size=1440,1000")
driver = webdriver.Chrome(options=options)
try:
driver.get("https://example.com")
print(driver.title)
finally:
driver.quit()
Headless mode is useful on machines without a display. For visual debugging, omit the headless argument so Chrome opens normally. Browser flags can behave differently across Chrome versions and operating systems; add only those your environment needs.
If you intentionally manage ChromeDriver yourself, Selenium supports supplying an explicit executable path through a Chrome Service object:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
service = Service(executable_path="/path/to/chromedriver")
driver = webdriver.Chrome(service=service)
try:
driver.get("https://example.com")
print(driver.title)
finally:
driver.quit()
Change the path to the driver executable for your environment. A machine-specific path is less portable than Selenium Manager or a project-managed setup. Selenium 4’s Chrome documentation states compatibility with Chrome 75 and newer, but version-specific problems can still depend on platform and browser features: Selenium with Chrome.
6. Cleanup and repeatable runs
Call driver.quit() when the script is finished. It ends the WebDriver session and closes its browser windows. Use try/finally as shown so cleanup also runs when navigation, lookup, or an assertion fails. driver.close() closes the current window; it is not a substitute for ending the entire session when the script is done.
For automated tests, keep setup and teardown in fixtures so each test has predictable browser lifecycle management. The Selenium project’s Python examples use pytest: Selenium Python examples.
7. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
ModuleNotFoundError: No module named 'selenium' |
Selenium was installed into a different Python environment. | Activate the intended virtual environment, then run python -m pip install -U selenium with the same Python command used to launch the script. |
| Chrome or ChromeDriver cannot start | Chrome is missing, cannot launch, or driver discovery failed. | Confirm Chrome launches on the machine, update Selenium in the active environment, and inspect the Selenium Manager diagnostics. If automatic management does not fit the environment, configure a driver with Chrome’s Service. |
| Driver and browser version error | An explicitly configured driver may not match the installed browser, or an old driver may precede the managed one on PATH. |
Check the Chrome and Selenium versions and the selected driver path. Remove stale path configuration or provide a compatible driver deliberately. |
NoSuchElementException |
The selector is wrong, the element is in another browsing context, or the page has not rendered it yet. | Inspect the page and selector; wait for presence or visibility. Switch to the correct frame or window if the target is not in the current context. |
TimeoutException |
The expected condition did not become true before the explicit wait expired. | Check whether the page reached the expected state, whether the locator is correct, and whether the site is still loading. Increase the timeout only when the condition legitimately takes longer. |
| Click intercepted or element not interactable | An overlay covers the target, it is hidden or disabled, or layout is still changing. | Wait for clickability, dismiss a legitimate overlay when appropriate, and ensure the target is visible and enabled before clicking. |
| Works locally but fails in a container or CI | The runtime may lack Chrome, required system libraries, a display, or network access needed for driver management. | Install and verify the browser in the execution image, use headless mode when there is no display, and check network and permissions for Selenium Manager. Record OS, Python, Selenium, Chrome versions, and the full error. |
8. Performance, reliability, and cost
Browser automation starts a real browser session, so reuse a session for related steps instead of launching Chrome for every small operation. Wait for the specific state you need rather than sleeping for a fixed duration: fixed delays make fast runs wait unnecessarily and may still be too short on a slow page. Keep selectors stable, close sessions in cleanup paths, and capture the version and error details when diagnosing failures.
For repeatable execution, pin your project’s Python dependencies and control the browser and driver versions used by your environment. Selenium Manager reduces manual driver setup, while an explicitly managed browser/driver pair gives you more control at the cost of maintaining that pairing. These are practical setup tradeoffs, not performance benchmarks. Selenium, Python, and Chrome are software components; local automation has no per-screenshot API charge, though running browsers consumes machine resources.
9. Or skip the browser setup
If your goal is a screenshot rather than browser interaction or a test, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation.
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}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
Cookie and consent banners are accepted like a visitor and removed before capture, along with supported newsletter popups and chat widgets; each of these steps can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Responses identify the page verdict and billing status in headers. An MCP server gives AI agents tools for screenshots, page information, and PDF capture. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is on every plan.
Sign up for 1,000 free screenshots a month, with no card required.
10. FAQ
Do I need to download ChromeDriver separately?
Usually not with a current Selenium setup: start with webdriver.Chrome() and let Selenium Manager handle driver discovery when needed. Use a manually managed driver only when your environment requires it.
Can I use Selenium without opening a visible browser window?
Yes. Add Chrome’s --headless argument through Options, as shown above. The machine still needs a working Chrome installation and compatible runtime dependencies.
Is Selenium the right tool for a one-off screenshot?
Selenium is useful when you need browser interaction, assertions, or control over the session. For a screenshot-only workflow, a screenshot API can avoid maintaining browser and driver setup.


