Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesBuild the pipeline in three steps: prepare an application endpoint, run Selenium WebDriver tests against a browser in the job or a Selenium Grid service, then save test reports and failure evidence as GitLab artifacts. A single browser in the job is the simpler starting point; use Grid when remote execution, parallel sessions, or broader browser coverage warrants its added capacity and security work.
The example below assumes a Python project, pytest, a GitLab Docker executor, and an application already available at a test URL. GitLab configuration depends on the runner, browser image, and deployment method, so treat the YAML as a pattern to adapt and verify—not a universal, pretested recipe.
As an Amazon Associate I earn from qualifying purchases.
How the pipeline is organized
GitLab reads pipeline configuration from .gitlab-ci.yml. Stages establish broad sequencing; jobs within a stage can run in parallel. A practical flow is to deploy or prepare the test target, run browser tests, and retain reports and debugging evidence. You can use needs to express dependencies and reduce waiting, but keep the dependency graph understandable. See GitLab CI/CD pipelines.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
- Prepare the target: deploy a review environment or choose an existing test URL that the runner can reach.
- Run Selenium: execute the test suite with a browser available in the job, or send WebDriver commands to a remote Grid endpoint.
- Keep evidence: publish framework reports, screenshots, and useful logs as job artifacts; configure a supported test report format to surface results in merge requests.
Decide which push, merge-request, or branch events should start the pipeline according to your review policy. Keep credentials in protected variables or an approved secret-management system; do not print them or put them in artifacts.
#1 Best Overall
Choose where the browser runs
| Execution shape | Best fit | What to configure | Trade-off |
|---|---|---|---|
| Browser available to the test job | A modest suite using one browser and a runner that can provide it. | Use an image that includes the test dependencies and browser, or a compatible browser service; verify the service alias, port, readiness, and runner network. | Fewer moving parts, but browser and test dependencies share the job environment. |
| Selenium Grid endpoint | Remote browser execution, parallel sessions, or multiple browser and operating-system combinations. | Point RemoteWebDriver at the Grid endpoint reachable from the job. Configure capacity, versions, networking, and access controls. | More flexible distribution and coverage, with extra infrastructure and capacity planning. |
Selenium WebDriver bindings issue browser commands through browser-specific drivers. Selenium Manager, available through Selenium bindings, can manage drivers automatically, but it cannot make a browser available if the execution environment does not provide one. Read Selenium getting started and the Selenium overview.
Browser in the job
For a small suite, the least complex setup is often a job image that already contains the needed browser and test dependencies. Another option is a browser or Selenium service container. GitLab provides the general image and services mechanisms; it does not make every Selenium image, alias, readiness check, or runner network arrangement interchangeable. In a Docker job, scripts run in the project build directory, so relative test and artifact paths are relative to that directory. See GitLab Docker jobs and GitLab services.
Remote execution with Grid
Grid routes WebDriver commands to remote browser instances. Standalone mode listens for RemoteWebDriver requests at http://localhost:4444 by default, but a GitLab job usually needs the hostname and port that are reachable from its own network—not necessarily localhost. Confirm the service alias, exposed port, and runner networking. Grid can distribute sessions across nodes and support multiple browser types and versions. Use it when that coverage or concurrency is needed, rather than adding it automatically to a one-browser suite. See Selenium Grid, Grid getting started, and When to Use Grid.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #2
Example: Python tests against a reachable test target
This example uses an already deployed application at TEST_URL, pytest, Python, and a Grid service named selenium. The Selenium container image and service configuration are intentionally not prescribed: choose a maintained image compatible with your runner, pin its version, and verify its readiness and networking before relying on this configuration. Replace the image placeholder with a real pinned Python image as well.
stages:
- test
selenium_tests:
stage: test
image: python:3.12.8
services:
# Replace with a verified, version-pinned Selenium image.
- name: selenium/standalone-chrome:4.49.0
alias: selenium
variables:
# The host must match the service alias and be reachable by this job.
SELENIUM_URL: "http://selenium:4444"
TEST_URL: "https://test.example.com"
before_script:
- python -m pip install --upgrade pip
- python -m pip install -r requirements.txt
script:
- pytest --junitxml=artifacts/junit.xml
artifacts:
when: always
expire_in: 1 week
reports:
junit: artifacts/junit.xml
paths:
- artifacts/
This YAML illustrates the pipeline shape; it is not a claim that a particular image and runner combination has been tested. Verify the selected Selenium image tag and browser version, that it accepts connections on port 4444, and that the runner’s executor connects the job to service containers. For browser-in-job execution, instead select a pinned test image with the browser installed and configure the WebDriver binding for that browser; omit the Grid service and RemoteWebDriver URL.
Minimal pytest test using RemoteWebDriver
The following test creates a remote Chrome session, visits the configured target, and always attempts to close the session. Install a Selenium binding in your project dependencies. Adapt assertions and browser capabilities to your application and Grid configuration.
Rank #3
import os
import pytest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
@pytest.fixture
def driver():
grid_url = os.environ["SELENIUM_URL"]
options = Options()
browser = webdriver.Remote(command_executor=grid_url, options=options)
try:
yield browser
finally:
browser.quit()
def test_homepage_loads(driver):
driver.get(os.environ["TEST_URL"])
assert driver.title
Pin compatible Selenium client and server/container versions in your dependency and image configuration. The Selenium downloads page lists version 4.49.0 as Stable, dated September 9, 2026; release status changes, so check Selenium downloads when selecting versions.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Prepare or deploy the application under test
The browser needs a URL reachable from the job or Grid browser, not merely from a developer’s workstation. For a deployed review environment, make deployment an earlier stage and pass its URL to the test job using an appropriate variable or artifact. If the target is already deployed, set the URL as a project variable or in the job configuration. Do not put credentials or sensitive data in the URL, logs, screenshots, or test reports.
When tests depend on deployment output, model that dependency with stages or a clear needs relationship. Keep the target environment alive until browser tests finish, and add cleanup only if your deployment process creates resources that need removal. The deployment commands and application lifecycle are project-specific; this example assumes the test URL already exists.
Rank #4
Save reports and failure evidence
Use artifacts:when: always so evidence is retained when tests fail. The example saves JUnit XML both as an artifact path and as a GitLab test report, where a supported report can appear in merge-request testing views. Selenium screenshots can also be written to the artifact directory when a test fails; include them in paths. Keep logs focused and scrub credentials or personal data before saving them.
Choose artifact retention and size deliberately: screenshots, browser logs, and reports can accumulate. GitLab documents artifact access and retention in job artifacts and report integration in testing.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Parallelism, capacity, and security
Scale only to measured demand
Grid is useful when you need remote distribution, parallel sessions, or browser and operating-system coverage beyond a single job browser. It also consumes infrastructure and requires enough browser capacity for the sessions you schedule. Selenium’s current Grid getting-started guidance offers 1 CPU and 1 GB RAM per browser as a reference, not a universal guarantee; actual needs vary, so measure performance continuously.
Best Value
Keep the endpoint private
Do not expose a Grid endpoint to the public internet. Selenium warns that an exposed Grid can give outsiders access to infrastructure and internal applications or files, and may let them run binaries. Restrict access with appropriate network controls and expose it only to the intended CI jobs. Selenium states: “Grid must be protected from external access using appropriate firewall permissions.” See Grid getting started.
Use controlled images and secrets
Pin job and service image versions so builds do not silently change when an upstream tag changes. If the pipeline builds or launches containers using Docker-in-Docker, first confirm the runner executor and security policy: GitLab’s documented Docker and Kubernetes executor setup requires privileged mode for that approach. GitLab recommends pinning a specific Docker-in-Docker image version and using TLS where possible; privileged execution is not the only container-build strategy. See GitLab Docker-in-Docker.
For GitLab 17.7 and later, GitLab recommends pipeline inputs over passing pipeline variables. GitLab also warns that pipeline variables have high precedence and can override variables defined elsewhere. Store secrets using protected variables and your organization’s secret-management policies, and avoid echoing them. See GitLab CI/CD variables.
Troubleshooting common failures
- Connection refused or timeout to WebDriver: Check that the service is running, the Grid port is correct, and
SELENIUM_URLuses a hostname reachable from the job. In a GitLab service setup, verify the declared alias and runner networking;localhostin the job generally means the job container itself. - Tests cannot find a browser or driver: Confirm the selected image actually contains a browser for browser-in-job execution. For remote execution, verify that the Grid image has a compatible browser and that the client uses the intended RemoteWebDriver endpoint. Selenium Manager can manage drivers through bindings but does not install an absent browser.
- Session creation fails or browser versions mismatch: Pin and align the Selenium client, Grid/server image, and browser versions where compatibility requires it. Review Grid logs and requested capabilities.
- The target URL works locally but not in CI: Test name resolution and access from the runner and from the browser container. Check whether the URL is internal, requires authentication, or is unavailable before deployment completes.
- Artifacts or reports are missing: Confirm the test command writes to the same path declared in
artifacts, relative to the project build directory. Check that the report is valid JUnit XML and thatwhen: alwaysis configured if it must survive a failed test job. - Pipeline cannot start Docker-in-Docker: Check executor support and privileged-mode policy for the selected setup. If enabling privileged mode is not acceptable, choose a build approach compatible with your infrastructure rather than weakening runner controls.
- Grid is slow or sessions queue: Compare concurrent session demand with available browser resources, inspect Grid and runner load, and measure before adding capacity. CPU and memory needs depend on the browser workload.
Or skip the browser setup
If your task is to capture a clean page image or PDF rather than exercise interactive browser behavior, ScreenshotNeo offers a website screenshot API and MCP server for developers. Its API can return PNG, JPEG, WebP, or PDF in one GET request. Cookie banners are accepted and removed, along with 60+ known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers state the page verdict and billing status.
For example, capture a page to WebP with cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for the request options and output formats. Python and Node.js examples are also available:
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}`);
ScreenshotNeo also provides an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. Its Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for 1,000 free screenshots a month—no card required.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




