Free tools Windows power users keep installed
One-click scans. No signup required.
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use capabilities in current WebdriverIO. It is the configuration property for requesting a browser, device, and other session features. desiredCapabilities is legacy JSON Wire Protocol terminology, not a second current WebdriverIO option. For modern W3C WebDriver requests, capability data goes inside a capabilities wrapper; alwaysMatch holds constraints that must apply, and firstMatch holds alternative ways to satisfy the request.
What capabilities mean in WebdriverIO
A WebDriver session starts with a request from the client to a remote end, such as a local driver or a browser grid. The request describes the browser and the features the client wants the remote end to provide. Those requested features are capabilities.
In a current WebdriverIO configuration, put them in the capabilities property. A common setup uses an array of capability objects, one for each requested session configuration:
export const config = {
capabilities: [{
browserName: 'firefox',
browserVersion: 'stable',
platformName: 'linux'
}]
}
That is WebdriverIO configuration syntax. It should not be confused with the lower-level W3C wire-request shape, which wraps capabilities in an object containing alwaysMatch and firstMatch. WebdriverIO handles the protocol request for you when you configure its test runner.
#1 Best Overall
How capabilities and desiredCapabilities differ
| Aspect | desiredCapabilities |
capabilities |
|---|---|---|
| Protocol generation | Legacy JSON Wire Protocol terminology and request shape. | Current WebdriverIO configuration property, aligned with the W3C WebDriver capability model. |
| Request shape | Legacy requests put a desiredCapabilities dictionary at the top level. |
W3C requests use a top-level capabilities wrapper; WebdriverIO config uses the capabilities property. |
| Matching | Expressed a set of desired values, with legacy processing also involving requiredCapabilities. |
W3C uses alwaysMatch for constraints shared by a request and firstMatch for alternative branches. |
| Extension names | Older implementations may use unprefixed extension keys. | Custom and vendor extensions should be namespaced, for example goog:chromeOptions or appium:options. |
| Compatibility | May still appear in older projects and with older drivers. | Use for current W3C-compatible WebDriver endpoints; an older driver that lacks WebDriver protocol support may require JSON Wire Protocol capabilities. |
The practical point is not that one spelling is a stylistic preference. They belong to different generations of the session-creation protocol. Current WebdriverIO validates user-defined capabilities against the WebDriver capability model and its test runner can fail early when they do not conform.
Is desiredCapabilities deprecated?
For modern WebDriver work, treat desiredCapabilities and requiredCapabilities as legacy fields and avoid using them in new configurations. The WebDriver specification retains legacy processing rules for them, which is why they remain visible in older examples and compatibility discussions. MDN likewise describes them as legacy and deprecated.
That does not mean every old driver has suddenly stopped accepting the old shape. WebdriverIO’s configuration guidance preserves a compatibility caveat: a driver that does not support the WebDriver protocol may require JSON Wire Protocol capabilities. If a project depends on such a driver, verify its protocol and documentation before changing the request format. Do not assume a W3C conversion is accepted by every historical endpoint.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteConvert desiredCapabilities to capabilities
Convert the browser and version keys
Start by moving the values into a WebdriverIO capabilities entry. A legacy example might look like this:
{
"desiredCapabilities": {
"browserName": "firefox",
"version": "stable"
}
}
For a current WebdriverIO configuration, use the modern property names and add any target-specific platform constraint your driver or grid requires:
export const config = {
capabilities: [{
browserName: 'firefox',
browserVersion: 'stable',
platformName: 'linux'
}]
}
The important migration is desiredCapabilities to capabilities, and, where applicable, the modern standard key browserVersion in place of a legacy version key. Values such as stable and platform strings must be understood by the specific driver or grid you target; do not assume a value supported by one service is portable to another.
Use the W3C form when constructing a protocol request
If you are building or inspecting the W3C request itself rather than editing WebdriverIO runner configuration, express constraints and alternatives inside the wrapper:
{
"capabilities": {
"alwaysMatch": {
"browserName": "firefox"
},
"firstMatch": [
{ "platformName": "linux" },
{ "platformName": "windows" }
]
}
}
Here, the browser requirement applies to every branch, while the remote end can match either the Linux or Windows branch. Use valid platform values for the target. With only one branch, the same browser request can be expressed with that object as the sole member of firstMatch; an alwaysMatch object can also express constraints that must apply. These are W3C request semantics, not a requirement to paste this raw wrapper into WebdriverIO’s capabilities array.
Rank #2
Namespace vendor and custom extensions
Standard capability names include browserName, browserVersion, and platformName. Driver-specific settings and custom extensions should use a namespace containing a colon. For example:
const capabilities = {
browserName: 'chrome',
'goog:chromeOptions': { args: ['headless'] },
'custom:caps': { team: 'qa' }
}
Other documented namespace examples include moz:firefoxOptions, sauce:options, and appium:options. Use the namespace and option structure recognized by the particular driver or service; a syntactically namespaced key is not a guarantee that every endpoint implements it.
Should you use alwaysMatch or firstMatch?
- Use
alwaysMatchfor requirements that must be true for any acceptable session, such as a particular browser name. - Use
firstMatchwhen the remote end may create the session using one of several alternative capability sets. - Use both when there are shared constraints plus alternatives. Each matching branch is considered alongside the shared constraints.
- Use a single branch when there is only one configuration to request. There is no need to manufacture alternatives just to use W3C syntax.
In normal WebdriverIO test-runner configuration, provide the capabilities in the structure the runner expects, typically an array of objects. The W3C matching model explains how those requests are represented and negotiated at the protocol level; it is not a reason to nest alwaysMatch inside each ordinary WebdriverIO capability object without checking the relevant configuration documentation.
Why a WebdriverIO capability configuration fails
A rejected session request usually means the requested key, value, request shape, or protocol does not fit the remote end. Work through the mismatch rather than changing several fields at once.
Legacy field used with a current endpoint
If the request uses top-level desiredCapabilities or requiredCapabilities, convert it to current WebdriverIO configuration and W3C-compatible capability names. Confirm that the driver supports W3C WebDriver before removing a legacy compatibility path.
Unsupported or incorrectly named capability
Check standard spelling first: use browserVersion, not the legacy version example, for a modern request. For driver or cloud-service settings, use the documented namespaced key. A vendor option without the expected namespace, or a namespace the endpoint does not recognize, can cause validation or session creation to fail.
Invalid value for the target grid
Names alone are not enough: the requested browser version, platform, and option values have to be supported by the remote end. Confirm accepted values for that target instead of copying a version or platform value from a different grid or local driver.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Wrong nesting level
Separate WebdriverIO runner configuration from a raw W3C HTTP request. In the runner, configure capabilities as expected by WebdriverIO. In a W3C protocol request, put alwaysMatch and firstMatch inside the top-level capabilities wrapper. Mixing the two shapes is a common source of confusing validation errors.
Old driver expects JSON Wire Protocol
If a formerly working setup rejects W3C keys after an upgrade, determine whether its driver supports the WebDriver protocol. WebdriverIO notes that older drivers without that support may require JSON Wire Protocol capabilities. The durable fix may be to update or replace the driver; where that is not possible, follow its compatibility requirements rather than assuming modern syntax will work.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Inspect what WebdriverIO requested and what it received
When a session starts but behaves differently from the configuration, compare the requested and negotiated values at runtime:
console.log(browser.requestedCapabilities)
console.log(browser.capabilities)
console.log(browser.isW3C)
browser.requestedCapabilitiesshows what the client asked for.browser.capabilitiesshows the capabilities assigned by the remote server.browser.isW3Creports whether the session is using the W3C protocol mode.
This comparison helps distinguish a configuration mistake from a remote-end choice: for example, whether the requested browser/version was sent as intended and what the server actually assigned. If session creation fails before a browser object is available, inspect the session error from the driver or service and validate the request against its supported capabilities.
Performance, reliability, and compatibility considerations
Capabilities are session-creation constraints, not a performance tuning system by themselves. A restrictive browser, version, or platform request can limit which remote environments match; alternatives in firstMatch can make a request flexible when several environments are acceptable. Conversely, listing alternatives does not guarantee that a particular branch exists or that the remote end will accept every extension.
Keep the request as specific as the test requires, and avoid carrying old, unused extension keys forward during migration. That makes validation errors easier to diagnose and reduces accidental dependence on a particular driver. For reliability, test changes against the actual local driver or grid endpoint: compatibility is determined by the protocol support and capabilities of that endpoint, not just by whether the JavaScript configuration parses.
If what you need is screenshots rather than WebdriverIO automation
ScreenshotNeo is not a replacement for WebdriverIO: WebdriverIO configures browser automation sessions, while ScreenshotNeo is a website screenshot API and MCP server. If your task is simply to capture a page as an image or PDF, it is an alternative to try first because it removes consent banners, popups, and chat widgets before the capture, and only clean shots are billed.
Or skip the browser setup
One GET request returns a screenshot; see the ScreenshotNeo API documentation for request options.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Cookie and consent banners, newsletter popups, and chat widgets can be removed before the shot, with each removal step configurable. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing; response headers report the page verdict and billing status. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, or another MCP client. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.
Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.
Frequently Asked Questions
Does the term desiredCapabilities still appear in WebDriver?
Yes. It remains in legacy protocol processing and older driver examples, so its presence in existing code does not make it the current WebdriverIO configuration property.
Can a capability request guarantee the exact browser the remote end will start?
It states what the client requests; the session result is reported separately in the negotiated capabilities. The remote endpoint must support and satisfy the request.
Recommended Free Tools
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.

