Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchSome links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Replace the deprecated initializer keys with a browser-specific Service object. Put the driver executable path in service.executable_path, the listening port in service.port, and driver-process arguments in service.args. Keep browser switches such as --headless in a browser Options object, then pass both objects to Selenium::WebDriver.for.
The migration in one view
Older Selenium Ruby code often puts several unrelated settings directly in the driver initializer:
driver = Selenium::WebDriver.for :chrome,
driver_opts: {args: ['--log-level=0']},
driver_path: '/path/to/chromedriver',
port: 9515
That shape is deprecated. The supported arrangement separates the local driver process from the browser session:
service = Selenium::WebDriver::Service.chrome
service.executable_path = '/path/to/chromedriver'
service.port = 9515
service.args << '--log-level=0'
options = Selenium::WebDriver::Options.chrome
options.add_argument('--headless')
driver = Selenium::WebDriver.for(:chrome, service: service, options: options)
The distinction matters: a Service manages starting and stopping the local driver, while Options describes the browser session. The Selenium Ruby changelog specifically deprecates passing driver_opts, driver_path, and port to the initializer and directs users to browser-specific Service classes.
#1 Best Overall
What each deprecated value becomes
| Deprecated initializer value | Replacement | What it controls |
|---|---|---|
driver_path |
service.executable_path |
The local driver executable, when you need to select an explicit file. |
port |
service.port |
The port used by the local driver service. |
driver_opts: { args: [...] } |
service.args |
Command-line arguments consumed by the driver process. |
Browser arguments such as --headless |
options.add_argument |
Command-line switches sent to Chrome, Firefox, or Edge. |
Do not mechanically move every argument into service.args. Driver-process arguments belong to the Service; browser flags, capabilities, and preferences belong to Options.
Step-by-step Chrome migration
1. Create the Chrome Service
Use the browser-specific factory:
service = Selenium::WebDriver::Service.chrome
This creates the object Selenium uses to manage the Chrome driver process.
2. Move the executable path, if required
Replace the old driver_path key with an assignment on the Service:
Recommended Free Tools
service.executable_path = '/path/to/chromedriver'
Use a path that exists and is executable in the environment where the Ruby process runs. If your application does not need to select a particular executable, leave this assignment out rather than retaining a stale path.
3. Move the port
service.port = 9515
A fixed port is useful when another part of your environment expects one, but it can collide with an existing process. If you set it, make sure the port is available for every parallel worker that uses it.
4. Move driver-process arguments
service.args << '--log-level=0'
These arguments affect the driver service, not the browser window. Add each argument deliberately; an argument that is meaningful to Chrome itself should instead be added to Chrome Options.
5. Keep browser settings in Options
options = Selenium::WebDriver::Options.chrome
options.add_argument('--headless')
Headless mode is a browser setting, so it remains in options. The same object is where you keep browser capabilities and preferences.
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 glitchesRank #2
6. Start the session with both objects
driver = Selenium::WebDriver.for(:chrome, service: service, options: options)
The keyword names are significant: use service: for the Service object and options: for the browser Options object.
A complete, runnable Chrome example
The following example shows all three migrated values and a browser argument in the correct locations:
require 'selenium-webdriver'
service = Selenium::WebDriver::Service.chrome
service.executable_path = '/path/to/chromedriver'
service.port = 9515
service.args << '--log-level=0'
options = Selenium::WebDriver::Options.chrome
options.add_argument('--headless')
driver = Selenium::WebDriver.for(
:chrome,
service: service,
options: options
)
begin
driver.navigate.to('https://example.com')
puts driver.title
ensure
driver.quit
end
Replace the executable path and target URL for your environment. The ensure block closes the browser even when navigation or an assertion raises an exception.
Firefox and Edge use the same separation
The factory changes with the browser, but the migration model does not.
Firefox
service = Selenium::WebDriver::Service.firefox
service.executable_path = '/path/to/geckodriver'
service.port = 9516
options = Selenium::WebDriver::Options.firefox
options.add_argument('-headless')
driver = Selenium::WebDriver.for(:firefox, service: service, options: options)
Edge
service = Selenium::WebDriver::Service.edge
service.executable_path = 'C:\path\to\msedgedriver.exe'
service.port = 9517
options = Selenium::WebDriver::Options.edge
options.add_argument('--headless')
driver = Selenium::WebDriver.for(:edge, service: service, options: options)
Chrome uses Service.chrome, Firefox uses Service.firefox, and Edge uses Service.edge. Match the executable to the browser and operating system installed on the machine.
How to classify an existing argument
When modernizing a large test suite, classify each old setting before moving it:
- Driver executable selection: assign
service.executable_path. - Driver listening port: assign
service.port. - Driver logging or service switches: append to
service.args. - Browser command-line switches: call
options.add_argument. - Browser capabilities or preferences: configure the browser Options object.
If you cannot tell which process consumes an argument, consult the documentation for that specific driver option rather than placing it in both objects. Duplicating a switch can produce confusing startup failures.
Rank #3
Common migration failures and fixes
“Unknown keyword” or deprecation warnings remain
Cause: one of driver_opts, driver_path, or port is still being passed to Selenium::WebDriver.for.
Fix: remove those initializer keys and pass only service: and options:. Search helper methods and factory wrappers as well as individual tests.
The browser flag has no effect
Cause: a browser flag was appended to service.args, where the browser never receives it.
Fix: move the flag to the matching Options object, for example options.add_argument('--headless') for Chrome.
The driver executable cannot be started
Cause: service.executable_path points to a missing, non-executable, or wrong-platform file.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Fix: verify the absolute path, file permissions, and that the executable matches the selected browser. Remove the explicit assignment if the environment supplies the correct driver another way.
The requested port is already in use
Cause: another driver process, test worker, or service owns the port.
Fix: choose an unused port and ensure parallel workers do not all set the same fixed value. A fixed port should be an intentional infrastructure choice, not a copied legacy default.
The session starts, but the test still fails
Cause: the migration changed process startup but not the browser capabilities, preferences, URL, or test assumptions.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Fix: isolate startup from test logic: first launch a minimal session, navigate to a known page, and print the title. Then restore application-specific Options and assertions one at a time.
Cleanup is unreliable
Cause: the test exits before quit runs.
Fix: wrap the session in begin ... ensure ... driver.quit ... end, as in the complete example. Service classes manage starting and stopping the local driver, but your test should still close the WebDriver session explicitly.
Verification checklist before committing the change
- Confirm the Selenium Ruby gem version used by the target project supports the Service API shown here.
- Confirm the browser-specific factory matches the browser under test.
- Check that every explicit executable path exists on the target machine.
- Check that a fixed port is available and unique where parallel execution is used.
- Review every former
driver_optsargument and classify it as a Service or browser Option. - Start a minimal session and navigate to a known URL.
- Run the full suite in the same operating-system and browser environment used by CI.
- Remove obsolete initializer keys so future gem upgrades do not depend on deprecated behavior.
The API documentation establishes the object layout; successful runtime behavior still depends on the installed Ruby gem, browser, driver executable, operating system, and local configuration.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Performance, reliability, and parallel runs
The Service migration does not make a browser session inherently faster. Its practical benefit is clearer ownership of startup settings, which makes failures easier to diagnose and configuration easier to vary per browser or worker. For parallel runs, avoid sharing one fixed port between services. Give each worker an available port and an executable environment it can access. Keep browser arguments in Options so changing headless or display behavior does not accidentally alter driver-process startup.
Free tools Windows power users keep installed
One-click scans. No signup required.
For repeatable builds, keep the Service and Options construction close to the code that owns the session, or expose a small factory that accepts the executable path, port, and browser settings as explicit parameters. This prevents hidden defaults from reintroducing deprecated initializer keys.
Best Value
Or skip the browser setup
If your goal is a static image or PDF rather than an interactive WebDriver session, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. Cookie and consent banners, newsletter popups, and chat widgets are removed before capture; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed as clean shots, and response headers identify the page verdict and billing status. Its MCP tools—take_screenshot, get_page_info, and capture_pdf—let Claude, Cursor, or another MCP client request captures.
See the ScreenshotNeo API documentation for parameters. This is a complete cURL call:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Equivalent Python:
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)
Equivalent Node.js:
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 includes full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF paper and page controls, custom CSS and JavaScript, click-before-capture actions, selector waits, delays or network-idle waits, request and resource blocking, custom headers, cookies, user agents and authorization, timezone and geolocation, transparent backgrounds, resizing, configurable caching, signed image links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API, and an OpenAPI specification. Parameter names used by other screenshot APIs also work, which can simplify a switch.
| Plan | Allowance | Price |
|---|---|---|
| Free | 1,000 shots/month | No card required |
| Starter | 3,000 shots | $5 |
| Growth | 15,000 shots | $15 |
| Pro | 60,000 shots | $39 |
| Scale | 250,000 shots | $99 |
| Business | 1,000,000 shots | $249 |
Every feature is included on every plan, and yearly billing provides two months free. Create a free ScreenshotNeo account to get 1,000 screenshots each month with no card; paid plans start at $5 for 3,000 shots.
Frequently Asked Questions
Do I put Chrome’s `–headless` switch in `service.args`?
No. Put browser switches in the Chrome Options object with `options.add_argument`; reserve `service.args` for driver-process arguments.
Is `service.executable_path` mandatory?
No. Set it only when you need an explicit driver executable. Otherwise omit the assignment and let the environment’s normal driver resolution apply.
Can one Service object be reused by several drivers?
Create and configure a Service for the session that owns it. Reusing a fixed port across concurrent sessions can cause collisions.
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.

