In addition to the standard Selenium capabilities and the W3C WebDriver spec, the Selenium server running on each HeadSpin host supports a number of custom capabilities below. In addition, the HeadSpin Selenium load balancer running in the cloud supports additional capabilities that control device selection and redundancy.
<code class="dcode">browserName</code> capability value for each browser
Browser
browserName
Chrome
chrome
Microsoft Edge
MicrosoftEdge, msedge
Chromium
chromium
Brave Browser
brave
Firefox
firefox
Safari
safari
Starting a new selenium session against a chromium based browser and chromedriver on a local host require <code class="dcode">chrome</code> as the <code class="dcode">browserName</code> capability. However, the HeadSpin platform requests a proper <code class="dcode">browserName</code> in the above table to create a new session in order to manage the browser instance on the HeadSpin platform. For example, please set brave as the <code class="dcode">browserName</code> capability value in the capabilities set to start a new selenium session against a Brave Browser instance.
Host capabilities
Capability
Description
Values
headspin:capture
Enable video and network capture. Default false. These capture components can be overriden individually by headspin:capture.video or headspin:capture.network. If set, the individual settings take precedence.
true, false
headspin:capture.video
Enable video capture. When set, this takes precedence over headspin:capture. Also, headspin:capture does not need to be set for this to take effect.
true, false
headspin:capture.video.browser.hwAcceleration
Enable hardware acceleration in video capture on an Intel CPU-based Windows machine. This capability improves the host machine's CPU usage for video capture feature during the session, but this capability limits changing the window size dynamically in the session. Please use headspin:initialScreenSize capability to set the browser size instead of calling Selenium window-handling APIs. These APIs will get error responses after starting the session. Default false.
true, false
headspin:capture.network
Enable network capture. When set, this takes precedence over headspin:capture. Also, headspin:capture does not need to be set for this to take effect.
true, false
headspin:capture.ignoreHosts
A list of ignored host:port regex patterns. These hosts are ignored from the network capture session. The pattern can be just a host name also, in which case all ports are matched. Please ensure the value escaped properly if it has language/context dependent string such as backslash.
e.g. ['abc\.example\.com:443', '.*\.mydomain.com']
headspin:capture.networkConfig
Configures the network used by the device during the capture session.
Allowed keys are shaping, redirectRules, spoofRules, headerRules. See Network Config below for details of each.
headspin:capture.networkKeepInSessionPatterns
Controls whether a destination host:port (or ip:port) is kept in the session after an error. By default any destination with an error (e.g. TLS exception) will be excluded from the session, to allow the app to perform as well as possible going forward. Add glob patterns here to keep a destination with an error in the session, to continue to try to parse the network protocol for that destination. This is a list of globs that must fully match host:port or ip:port.
e.g. ['headspin.io:443', '*.headspin.io:443']
headspin:capture.disableHttp2
Prevent the device from using HTTP/2 during network capture. Default false.
true, false
headspin:capture.startTimeout
Set timeout in seconds to wait for the capture session preparation to be ready as part of a new session creation up to 600 seconds. It is similar to how long the new session creation should wait to prepare capture session via Session API as part of it. Default 300 seconds.
200, "500"
headspin:session.name
Set the name of the HeadSpin session. For existing sessions, the name can be updated in the Waterfall UI or via the Session Annotation API.
string
headspin:session.description
Set the description of the HeadSpin session. For existing sessions, the description can be updated in the Waterfall UI or via the Session Annotation API.
string
headspin:sessionTags
Tag the session with an array of key, value tags. Tags will only be applied to sessions that have performance capture enabled. e.g. [{"demo": "tag"}, {"hello": "world"}]
headspin:testName
Sets the User Flow name of this capture session for Performance Monitoring, where all sessions with the same User Flow name are grouped together. To use this, at least one of the following capture components must be active for the session: video or network capture. For details on adding passed/failed/excluded status on the session, see User Flow Status below.
e.g. app_load_test
headspin:testData
Add custom measurements to the session. This data will be inserted into the performance test, for this session ID
e.g. [{"key":"App Load Time", "value":20, "title": "Custom Metrics", "units": "seconds"}]
Starting the session with this set to true allows interaction with the device via the remote control UI during the session. This should be used with tools such as Appium Inspector, with which you may manually interact with the device during a session. If this is false, the device will be in view-only mode during the session. If the device is already locked by the user (by accessing it in remote control UI or via API), then an automation session cannot be started. Default false.
true, false
headspin:waitForAvailableTimeout
Set timeout to wait for a locked device to be available. Defaults to 60 seconds or headspin:newCommandTimeout if provided.
e.g. 90
headspin:newCommandTimeout
Set request timeout from seleniumserver to each WebDriver which is running behind seleniumserver. Defaults to 900 seconds.
e.g. 120
headspin:initialScreenSize
Set innerWidth/innerHeight size in the create session process. The WebDriver Set Window API sets outerWidth/outerHeight size, but this capability is for innerWidth/innerHeight. The maximum size depends on the host machine. The width on macOS can be larger than the screen width, but the height cannot. On Windows, both can be up to the screen size. The width and height of the screenshot API result depend on the innerWidth/innerHeight. Our video capture on browsers also depends on it.
e.g. {"width": 500, "height": 300}
Capability
Description
Values
headspin:driverLogLevel
Set log level to the WebDriver when it starts. The available format depends on each driver. For example, chromedriver allows one of ALL, DEBUG, INFO, WARNING, SEVERE, OFF. Geckodriver is fatal, error, warn, info, config, debug, trace.
e.g. DEBUG (Chromium drivers), debug (Gecko driver)
headspin:enableJSConsoleLog
Enable to record the browser JavaScript console log for Firefox and Chromium browsers. In Firefox, the console logs will be part of selenium.log in the capture session. Chromium browsers will be in the device.log. Default false.
true, false
headspin:screenshotSource
Configure the screenshot source. The available values are default and camera. camera means taking a screenshot via the Camera Device (CD) instead of Appium. This option does not affect taking an element screenshot. Please read A/V Box API about the Camera Device. It returns an error response if it failed to take a screenshot via the Camera Device. The value will be default if the device under test does not have a Camera Device associated with it. Default camera.
default, camera
headspin:forceQuitSession
Handle a delete session request similar to unlock the device in order to quit the session immediately after reaching the request to the Appium server. For example, driver.quit() quits the session immediately even if the previous commands are waiting for responses. Then, these waiting response requests will get invalid session id responses. This helps to quit a session early while the session has no response commands so long. This behavior is similar to quitting Appium process forcefully in the local Appium run. Default false
true,false
For scheme
Capability
Description
Value
headspin:allowFileScheme
Allow file:// scheme as Navigate To command. Defaults to false.
true, false
headspin:allowChromeScheme
Allow chrome:// scheme as Navigate To command. Defaults to false.
true, false
HeadSpin commands
These HeadSpin commands are designed to be run by the Execute Script interface.
Command Name
Description
Arguments
headspin:quitSession
End the session and optionally set the session's user flow status at the same time. See User Flow Status below.
HeadSpin collects JavaScript console logs when <code class="dcode">headspin:enableJSConsoleLog</code> is enabled in a capture session before ending the session. The log can be downloaded from the Waterfall UI or the Session API. JavaScript console logs are in <code class="dcode">jsconsole.log(</code>1) for Chromium browsers and part of <code class="dcode">selenium.log</code> for Firefox.
To get logs for Chromium browsers, use Selenium's log capture command and specify the <code class="dcode">browser</code> type. If you already accessed the <code class="dcode">browser</code> type log during a session, HeadSpin will only collect the <code class="dcode">browser</code> type log after the command runs. The log capture has the log level <code class="dcode">ALL</code> and sets the <code class="dcode">browser</code> type over the loggingPrefs capability by default.
(1) Note that previously <code class="dcode">device.log</code> was used to save the log data instead of <code class="dcode">jsconsole.log</code>. The <code class="dcode">device.log</code> will be unavailable as the JavaScript console log.
Load balancer capabilities
Capability
Description
Values
headspin:selector
A selector string of the device to use. This takes precedence over browserName and browserVersion. See selectors for the selector syntax. The load balancer will consider all the devices in the pool and use the healthiest that is most available to run the session. browserName will be used as part of sku, and browserVersion will be used as part of os_version.
os_version: 80.0.361.62
headspin:requestTimeout
Handle a request timeout from AppiumLB to each devices. It affects only when a client communicates with the target Appium server via AppiumLB. Defaults to 1200 seconds (20 minutes).
e.g. 120
Limitations
● File download is restricted. Browsers do not download files on to the host machine. This may not be changed using capabilities or DevTools protocols.
● Window size depends on the host machine environment.
● Navigate To command accepts below schemes. Please contact us if you want to send other schemes.
HeadSpin Selenium sessions return errors directly from the underlying Selenium driver without modification. Additionally, the Headspin platform may return the following extra errors:
HTTP status code
Error (error)
Note
How to Resolve
400
invalid argument
Request body is invalid or API token in the request is invalid.
Make sure the API token is valid or selenium commands are correct. This error could also happen when browserName and browserVersion are incorrect in the capabilities.
403
session not created
The device is already locked.
Make sure the device under test is not in use by others.
404
invalid session id
Cannot find active session id on the host.
Run your tests from session that was created.
405
unknown method
The request is wrong or not allowed on the host
Please contact us if the command had errors on only our platform.
408
timeout
The operation did not complete.
Retry the command. Increasing timeout using the headspin:newCommandTimeout capability should help.
500
session not created
Failed to create a new session.
Please contact support if this continues to happen.
500
unknown error
An unknown error occurred.
Please contact support if this continues to happen.
500
timeout
The session has been expired.
Run your tests from session creation again.
Setting the Selenium versions
Check available Browser versions
HeadSpin host provides the list of available browser versions as API. It helps to confirm which browser versions can run on the host machine.
The <code class="dcode">available</code> is available browser versions. You can specify them with <code class="dcode">browserName</code> and <code class="dcode">browserVersion</code>. The <code class="dcode">default</code> is chosen if a create session capabilities has no <code class="dcode">browserVersion</code>.
Please contact us if you would like to use a version which is not in the list.
Network Config
Key Name
Description
Values
shaping
(Chromium browsers only) Network conditioning targets. Rate targets are upper bounds on the native link speed. Round trip time and packet loss are in addition to the behavior of the native link. All values must be zero or positive. down is the download rate in megabits per second (mbps). up is the upload rate in megabits per second (mbps). rtt is the round trip time in millisecond for latency.
e.g. {"down": 5.1, "up": 1.2, "rtt": 10}
redirectRules
A list of rules host_regex=destination_host. If the host regex matches a host, the request will be rewritten as if the client sent it to destination_host instead. Backtick back references are allowed in the destination host.
e.g. ["foo\.com=bar.com", "(.*)headspin\.io=\1headspin.com"]
spoofRules
A list of rules host_regex=destination_host. If the host regex matches a host, the request IP will be changed to the IP resolved by destination host, as if the DNS record for the original host were changed to the destination host's.
e.g. ["foo\.com=13.33.148.190", ".*\.headspin.io=13.33.148.51"]
headerRules
A list of rules host_regex=header:value. If the host regex matches, the header will be injected into the request. Multiple headers of the same name will be comma separated in the final request. Backtick back references are allowed in the header and value.
e.g. [".*=X-Custom:MyApp"]
User Flow Status
To mark sessions passed, failed, or in some error state, you can either use a HeadSpin Selenium command to end the session, or use the Performance Monitoring API at any time. In either case, the session must be attached to a user flow by specifying <code class="dcode">headspin:testName</code> (this in turn requires that capture is turned on for the session, see description in the Selenium capabilities section).
Valid user flow status strings are: <code class="dcode">passed</code>, <code class="dcode">failed</code>, <code class="dcode">excluded</code>, and <code class="dcode">not_set</code>.
Note: If a session gets attached to a user flow and its status is set to passed, failed, or excluded, standard tags will be automatically added to the session. For more details on what these standard tags are, see Annotating Your Session: Session Tags.
Set user flow status using the <code class="dcode">headspin:quitSession</code> command
Set <code class="dcode">headspin:testName</code> when starting the session. This is required for the next step to work.
End the session by sending the command <code class="dcode">headspin:quitSession</code> with the argument <code class="dcode">{"status": <user flow status>}</code>.
For example, the Python script below sets the session's status to <code class="dcode">excluded</code>:
from selenium import webdriver
caps = {
... # Other capabilities
"headspin:testName": "test user flow", # Required to link session to user flow
"headspin:capture": True # Required to have a capture session
}
driver = webdriver.Remote('<Web Driver URL>', caps)
# Perform tests
...
response = driver.execute_script('headspin:quitSession', {'status': 'excluded'})
This will end the session and set its user flow status at the same time. It can be used in place of the <code class="dcode">driver.quit()</code> command to end the session. When called without any argument, it has the same effect as <code class="dcode">driver.quit()</code>.
If the command is successful, there will be no return value (<code class="dcode">response is None</code> is <code class="dcode">True</code>). However, if an argument is given but it could not be processed into a valid user flow status, then a string containing information about the problem will be returned. The session will still end, but no user flow status will be set.
Set user flow status using Performance Monitoring API
Set <code class="dcode">headspin:testName</code> when starting the session, or link the session to a user flow after it has started using the Performance Monitoring API.
POST to the Performance Monitoring API to set the status of the session, using the session ID from the driver.
For example, the Python script below sets the session's status to <code class="dcode">passed</code> using <code class="dcode">requests</code> to post to the API:
import requests
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
# Start a session with capture
driver = webdriver.Remote(command_executor=url, desired_capabilities=capabilities)
# Set api_token in the header
headers = {
'Authorization': 'Bearer <your_api_token>'
}
perf_data = {
'session_id': driver.session_id,
'status': 'passed'
}
requests.post('https://api-dev.headspin.io/v0/perftests/upload', headers=headers, json=perf_data)
Applying labels automatically
<code class="dcode">headspin:autoLabel</code> allows a session to add session annotations without separate session annotation API calls. This feature starts a tracking timer when a request reaches a pbox or the pbox gets a response from the WebDriver running on the pbox. If the pbox already has a running tracking timer with the same label name, the pbox will end the timer and create a new label using the given label name.
The diagram below shows how a pbox starts a tracking timer when it receives a request and stops the timer when the pbox handles the response.
<code class="dcode">headspin:autoLabel</code> has the structure below. The top key is a label name you want to create. The value contains rules to match which requests should be labeled with the provided name. Keys and values surrounded by <code class="dcode"><></code> can be customized.
{
"": {
"onCommand": [
{
"method": "<HTTP request method like GET>",
"endpoint": "<WebDriver command expected to match like /session/:sessionId/title>"
},
{
"method": "<HTTP request method like POST>",
"endpoint": "<WebDriver command expected to match like /session/:sessionId/url>",
"body": "<Expected string to be match with as a regular expression>"
},
#...
],
"category": "<category name>"
}
}
The top level key will be the label name.
Key Name
Description
Values
<your label name>
A string that will be the label name. The value is JSON Object which has the below items.
{"my test label": {"onCommandStart": [...], ...}}
The value of the above label name configures the rule.
Key Name
Description
Values
onCommand
An array to control labeling rule. Commands in this key works on both timing,onCommandStart and onCommandEnd. See the below Commands for the details.
(Optional, default user) A string that is the type of the label. The label type determines how HeadSpin responds to the label. See Available session label types in Session Annotation API for details.
user
category
(Optional) A string that is the category of the label. The label category is converted to lower case.
my labels
data
(Optional) Any useful JSON-serializable content associated with this label.
{"my": "data"}
pinned
(Optional, default false) A boolean flag indicating whether the label is pinned to the session or not. Pinned labels are shown by default when viewing a session, under the right panel's Details section. Pinned labels cannot be deleted.
false
video_box
(Optional) Coordinates of bounding boxes provided as nested arrays in the format [[x0, y0, x1, y1], ...]. See the Applying spatial filtering in video analyses in Session Annotation API for details.
[[0,0,100,200], [0,0,500,800]]
Labeling rules
<code class="dcode">onCommand</code>, <code class="dcode">onCommandStart</code> and <code class="dcode">onCommandEnd</code> define when the label is created with what rules.
The below sequence indicates when each command key is called. <code class="dcode">onCommandStart</code> is when the pbox gets a request. <code class="dcode">onCommandEnd</code> is when the WebDriver returns a request to the pbox. onCommand includes both cases. This time period by onCommand should be the same as labels in <code class="dcode">selenium-commands</code> category on a captured session.
<code class="dcode">headspin:autoLabel</code> detects a command if the command should be labeled automatically by checking its HTTP request <code class="dcode">method</code>, the <code class="dcode">endpoint</code>, and the <code class="dcode">body</code>:
Key Name
Description
Values
method
A string that is http request method.
GET, POST
endpoint
A string that is http request path. The format follows WebDriver endpoint defined in W3C or JsonWireProtocol. The string can have placeholders to handle arbitrary string part like session id in the path. For example, :sessionId is the placeholder of the {session id} in WebDriver endpoint defined in W3C or :sessionId in JsonWireProtocol. Available placeholders are :sessionId, :elementId, :name, :propertyName, :windowHandle (only JsonWireProtocol), :other (only JsonWireProtocol) and :key (only JsonWireProtocol).
/session/:sessionId/url
body
(Optional) A string to search the string as a regular expression in the http request body.
subdomain.headspin.io/.*
Example
<code class="dcode">onCommandStart</code>
The below example only has <code class="dcode">onCommandStart</code>. It means the pbox starts or ends and creates a label when matched requests come to the pbox.
# Ruby
firefox = Selenium::WebDriver.for(:remote,
url: 'https://{headspin-host}:{headspin-port}/v0/{your-api-token}/wd/hub',
desired_capabilities: { browserName: 'firefox', 'headspin:capture': true,
'headspin:autoLabel': {
'Do something test-automation page': {
'onCommandStart': [
{'method': 'POST', 'endpoint': '/session/:sessionId/url', 'body': 'https://www.headspin.io/platform/test-automation/'},
{'method': 'POST', 'endpoint': '/session/:sessionId/url', 'body': 'https://www.headspin.io/platform/local/'}
],
'category': 'open headspin site',
'label_type': 'page-load-request'
}
}
}
)
firefox.get 'https://www.headspin.io'
# The pbox starts a tracking timer as 'Do something test-automation page' label name
# when the below request reaches the pbox since the URL matches the first rule
# in 'onCommandStart'.
firefox.get 'https://www.headspin.io/platform/test-automation/'
# do something
# The pbox ends the timer and create a label named 'Do something test-automation page'
# when the below request reaches the pbox since the URL matches the seconds rule
# in 'onCommandStart'.
firefox.get 'https://www.headspin.io/platform/local/'
# do something
# The pbox starts a tracking timer a new label named 'Do something test-automation page'
firefox.get 'https://www.headspin.io/platform/local/'
# The pbox creates a label as 'Do something test-automation page'.
firefox.get 'https://www.headspin.io/platform/test-automation/'
firefox.quit
<code class="dcode">onCommand</code>
The below is another example with <code class="dcode">onCommand</code>. It means when a command matches to the rule, the pbox labels the command as the given label name, <code class="dcode">Do something test-automation page</code>. The time duration must be the same as the command time duration in <code class="dcode">selenium-commands</code> category.
# Python
firefox = webdriver.Remote(
'https://{headspin-host}:{headspin-port}/v0/{your-api-token}/wd/hub',
{ 'browserName': 'firefox', 'headspin:capture': True,
'headspin:autoLabel': {
'Do something test-automation page': {
'onCommand': [
{'method': 'POST', 'endpoint': '/session/:sessionId/url', 'body': 'https://www.headspin.io/'}
],
'category': 'open headspin site',
'label_type': 'page-load-request'
}
}
}
)
# The pbox starts a tracking timer as 'Do something test-automation page' label name
# when the pbox gets this request.
# The pbox ends the timer when it receives a response by the driver,
# before responding it to the client.
firefox.get('https://www.headspin.io')
# No nothing
firefox.get('https://subdomain.headspin.io/')
# do something
# The pbox starts a tracking timer as 'Do something test-automation page' label name
# when the pbox gets this request.
# The pbox ends the timer when it receives a response by the driver,
# before responding it to the client.
firefox.get('https://www.headspin.io')
firefox.quit()
<code class="dcode">onCommandStart</code> and <code class="dcode">onCommandEnd</code>
The below is combination of <code class="dcode">onCommandStart</code> and <code class="dcode">onCommandEnd</code>. A pbox starts a tracking timer when a request matches either <code class="dcode">onCommandStart</code> or <code class="dcode">onCommandEnd</code>. It stops the timer when a request matches either <code class="dcode">onCommandStart</code> or <code class="dcode">onCommandEnd</code> after the above request.
# Python
firefox = webdriver.Remote(
'https://{headspin-host}:{headspin-port}/v0/{your-api-token}/wd/hub',
{ 'browserName': 'firefox', 'headspin:capture': True,
'headspin:autoLabel': {
'Do something test-automation page': {
'onCommandStart': [
{'method': 'POST', 'endpoint': '/session/:sessionId/url', 'body': 'https://www.headspin.io/'}
],
'onCommandEnd': [
{'method': 'GET', 'endpoint': '/session/:sessionId/element/:elementId/text'}
],
'category': 'open headspin site',
'label_type': 'page-load-request'
}
}
}
)
# The pbox starts a tracking timer as 'Do something test-automation page' label name
# when the pbox gets this request.
firefox.get('https://www.headspin.io')
# do something
# The pbox ends the timer and create a label named 'Do something test-automation page'
# when the pbox receives the below request against the driver as 'onCommandEnd'.
firefox.title()
# do something
# The pbox starts a tracking timer as 'Do something test-automation page'
# when the pbox receives the below request against the driver as 'onCommandEnd'.
firefox.title()
# do something
# The pbox ends the timer and create a label named 'Do something test-automation page'
# when the pbox receives the below request against the driver as 'onCommandEnd'.
firefox.title()
firefox.quit()
Troubleshooting
For Safari 16.4 and higher, including 17, the <code class="dcode">com.apple.WebKit.Networking</code> process can crash when a delete cookies command is issued before opening a URL. From the perspective of the client, it could result in an 'invalid session id' error response to a new session request. To avoid the error, please do not use cookie deletion commands such as <code class="dcode">driver.manage.delete_all_cookies</code> before opening a URL.