This specification defines the WebDriver API, a platform and language-neutral interface and associated wire protocol that allows programs or scripts to introspect into, and control the behaviour of, a web browser. The WebDriver API is primarily intended to allow developers to write tests that automate a browser from a separate controlling process, but may also be implemented in such a way as to allow in-browser scripts to control a — possibly separate — browser.

The WebDriver API is defined by a wire protocol and a set of interfaces to discover and manipulate DOM elements on a page, and to control the behaviour of the containing browser.

This specification also includes a normative reference serialisation (to JSON over HTTP) of the interface's invocations and responses that are to be used by browser vendors to ensure interoperability.

If you wish to make comments regarding this document, please email feedback to public-browser-tools-testing@w3.org. All feedback is welcome, and the editors will read and consider all feedback.

This specification is still under active development and may not be stable. Any implementors who are not actively participating in the preparation of this specification may find unexpected changes occurring. It is suggested that any implementors join the WG for this specification. Despite not being stable, it should be noted that this specification is strongly based on an existing Open Source project — Selenium WebDriver — and the existing implementations of the API defined within that project.

Introduction

The WebDriver API aims to provide a synchronous API that can be used for a variety of use cases, though it is primarily designed to support automated testing of web apps.

Intended Audience

This specification is intended for implementors of the WebDriver API. It is not intended as light bed time reading.

Relationship of WebDriver API and Existing Specifications

Where possible and appropriate, the WebDriver API references existing specifications. For example, the list of boolean attributes for elements is drawn from the HTML specification. When references are made, this specification will link to the relevant sections.

Naming the Two Sides of the API

The WebDriver API can be thought of as a client/server process. However, implementation details can mean that this terminology becomes confusing. For this reason, the two sides of the API are called the "local" and the "remote" ends.

Local
The user-facing API. Command objects are sent and Response objects are consumed by the local end of the WebDriver API. It can be thought of as being "local" to the user of the API.
Remote
The implementation of the user-facing API. Command objects are consumed and Response objects are sent by the remote end of the WebDriver API. The implementation of the remote end may be on a machine remote from the user of the local end.

There is no requirement that the local and remote ends be in different processes. The IDLs given in this specification SHOULD be used as the basis for any conforming local end implementation.

Conformance Requirements

All diagrams, examples, and notes in this specification are non-normative, as are all sections explicitly marked non-normative. Everything else in this specification is normative.

The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in the normative parts of this document are to be interpreted as described in [[!RFC2119]]. The key word "OPTIONALLY" in the normative parts of this document is to be interpreted with the same normative meaning as "MAY" and "OPTIONAL".

Conformance requirements phrased as algorithms or specific steps may be implemented in any manner, so long as the end result is equivalent.

Conformance Classes

This specification defines three broad conformance classes:

Local End
This represents the client side of the protocol, which is usually in the form of language-specific libraries providing an API on top of the WebDriver protocol. This specification does not place any restrictions on the details of those libraries above the level of the wire protocol.
Remote End
This is the server side of the protocol, which is usually implemented by a web browser or similar user agent. Defining the behaviour of the remote end in response to the WebDriver protocol forms the largest part of this specification.
Intermediary Node
Intermediary nodes are those that act as proxies, implementing both the client and server sides of the protocol. Intermediary nodes must be black-box indistinguishable from remote ends from the point of view of local end and so are bound by the requirements on remote ends in terms of the wire protocol. However they are not expected to implement commands directly.

Terminology

In equations, all numbers are integers, subtraction is represented by “−”, and bitwise OR by “|”. The characters “(” and “)” are used to provide logical grouping in these contexts.

Common Infrastructure

Style Pixel Values

When asked to normalize style pixel values to integer for a value s:

  1. Let trimmed string be a substring of s where the suffix "px" is removed.
  2. Let pixels be the result of parsing trimmed string as an integer.
  3. If pixels is not a valid integer or the previous operation did not succeed, return 0.
  4. Return pixels.

When asked to normalize style pixel values to floating point for a value s:

  1. Let trimmed string be a substring of s where the suffix "px" is removed.
  2. Let pixels be the result of parsing trimmed string as a float.
  3. If pixels is not a valid float or the previous operation did not succeed, return 0.0.
  4. Round off pixels using ceil so that it has no more than four decimals.
  5. Return pixels.

These operations are almost equivalent to calling parseInt and parseFloat from [[!ECMA-262]] with the exception that non-valid integer or float return values are returned as 0 or 0.0.

Top Level Browsing Context no longer open

A top level browsing context is no longer open if it has been discarded

The WebDriver Protocol

Introduction

TODO

Common Infrastructure

Algorithms

Various parts of this specification are written in terms of step-by-step algorithms. The details of these algorithms do not have any normative significance; implementations are free to adopt any implementation strategy that produces equivalent output to the specification. In particular algorithms in this document are optimised for readability rather than performance.

Where algorithms that return values are fallible, they are written in terms of returning either success or error. A success value has an associated data field which encapsulates the value returned, whereas an error response has an associated error code.

Commands

The WebDriver protocol is organised into commands. Each HTTP request with a method and template defined in this specification represents a single command and therefore each command produces a single HTTP response. In response to a command, a remote end will run a series of actions against the remote browser.

Each command defined in this specification has an associated list of remote end steps. This provides the sequence of actions that a remote end takes when it recieves a particular command.

Processing Model

The remote end acts as a HTTP server reading requests from the client and writing responses, typically over TCP socket. For the purposes of this specification we model the data transmission between a particular local end and remote end with a connection to which the remote end may write bytes and read bytes. However the exact details of how this connection works and how it is established are out of scope.

After such a connection has been established, a remote end MUST run the following steps:

  1. Read bytes from the connection until a complete HTTP request can be constructed from the data. Let request be a request object constructed from the received data, according to the requirements of [[!RFC7230]].

  2. Let request match be the result of the algorithm to match a request with request's method and url as arguments.

  3. If request match is of type error, send an error with request match's error code and jump to step 1.

    Otherwise, let command, session id and element id be request match's data.

  4. If command is not new session:

    1. If session id is not equal to the id of any session in the list of active sessions, send an error with error code invalid session id, then jump to step 1 in this overall algorithm.

      Otherwise, let the current session be the session with id session id.

  5. If request's method is POST:

    1. Let parse result be the result of parsing as JSON with request's body as the argument.

    2. If parse result is an error or if it is a success but its associated data is not an Object object, send an error with status error code invalid argument and jump back to step 1 in this overall algorithm.

      Otherwise, let parameters beparse result's data.

    Otherwise, let parameters be null

  6. Let response data be a command response object obtained by running the remote end steps for command with arguments element id and parameters.

  7. If response data is an error, send an error with error code equal to response data's error code.

    Otherwise send a response with status 200 and response data's data.

  8. Jump to step 1.

When required to send an error, with error code, a remote end must run the following steps:

  1. Let http status and name be the error response data for error code.

  2. Let data be a new JSON Object.

  3. Let message be an implementation-defined string containing a human-readable description of the reason for the error.

  4. Set the properties of data with values ("error", name), ("message", message).

  5. Send a response with status and data as arguments.

When required to send a response, with arguments status and data, a remote end must run the following steps:

  1. Let response be a new response.

  2. Set response's status to status, and status message to the string corresponding to the description of status in the status code registry.

  3. If data is not null, let response's body be the result of serializing as JSON with data as the argument.

  4. Let response bytes be the byte sequence resulting from serializing response according to the rules in [[!RFC7230]].

  5. Write response bytes to the connection

Routing Requests

Request routing is the process of going from a HTTP request to the series of steps needed to implement the command represented by that request.

A remote end has an associated URL prefix, which is used as a prefix on all WebDriver-defined URLs on that remote end. This must either be the empty string, or an absolute path relative url.

In order to match a request given a method and url, the following steps must be taken:

  1. Let endpoints be a list containing each row in the table of endpoints.

  2. Remove each entry in endpoints for which the concatenation of the url prefix and the production in the "url" column does not match url according to the rules in [[!URI-Template]].

  3. If there are no entries in endpoints, return an error with code unknown command.

  4. Remove each entry in endpoints for which the "method" column is not an exact case-sensitive match for method.

  5. If there are no entries in endpoints, return an error with code unknown method.

  6. There is now exactly one entry in endpoints; let entry be this entry.

  7. If the match in step 2 populated a template variable called "sessionId", let session id be the value it was populated with. Otherwise let session id be null.

  8. If the match in step 2 populated a template variable called "elementId", let element id be the value it was populated with. Otherwise let element id be null.

  9. If the match in step 2 populated a template variable called "name", let name be the value it was populated with. Otherwise let name be null.

  10. Let command be the command represented by the "command" column of entry.

  11. Return success with data session id, element id and command.

List of endpoints

The following table of endpoints lists the method, URL and command for each WebDriver command.

Method URL Command
POST /session New Session
DELETE /session/{sessionId} Delete Session
GET /session/{sessionId}/url Get
GET /session/{sessionId}/url Get Current Url
POST /session/{sessionId}/back Go Back
POST /session/{sessionId}/forward Go Forward
POST /session/{sessionId}/refresh Refresh
GET /session/{sessionId}/title Get Title
GET /session/{sessionId}/window_handle Get Window Handle
GET /session/{sessionId}/window_handles Get Window Handles
DELETE /session/{sessionId}/window_handle Close
POST /session/{sessionId}/window/size Set Window Size
GET /session/{sessionId}/window/size Get Window Size
POST /session/{sessionId}/window/maximize Maximize Window
POST /session/{sessionId}/window Switch To Window
POST /session/{sessionId}/frame Switch To Frame
POST /session/{sessionId}/frame/parent Switch To Parent Frame
POST /session/{sessionId}/element Find Element
POST /session/{sessionId}/elements Find Elements
GET /session/{sessionId}/element/{elementId}/displayed Is Displayed
GET /session/{sessionId}/element/{elementId}/selected Is Selected
GET /session/{sessionId}/element/{elementId}/attribute/{name} Get Element Attribute
GET /session/{sessionId}/element/{elementId}/css/{propertyName} Get CSS Value
GET /session/{sessionId}/element/{elementId}/text Get Element Text
GET /session/{sessionId}/element/{elementId}/name Get Element Tag Name
GET /session/{sessionId}/element/{elementId}/rect Get Element Rect
GET /session/{sessionId}/element/{elementId}/enabled Is Enabled
POST /session/{sessionId}/execute Execute Script
POST /session/{sessionId}/execute_async Execute Async Script
GET /session/{sessionId}/cookie Get Cookie
GET /session/{sessionId}/cookie/{name} Get Cookie
POST /session/{sessionId}/cookie Add Cookie
POST /session/{sessionId}/timeouts Set Timeouts
POST /session/{sessionId}/actions Actions
POST /session/{sessionId}/element/{elementId}/click Element Click
POST /session/{sessionId}/element/{elementId}/tap Element Tap
POST /session/{sessionId}/element/{elementId}/clear Element Clear
POST /session/{sessionId}/element/{elementId}/sendKeys Element Send Keys
POST /session/{sessionId}/dismiss_alert Dismiss Alert
POST /session/{sessionId}/accept_alert Accept Alert
GET /session/{sessionId}/alert_text Get Alert Text
POST /session/{sessionId}/alert_text Send Alert Text
GET /session/{sessionId}/screenshot Take Screenshot

Handling Errors

Errors are represented in the WebDriver protocol with a HTTP response with a HTTP status in the 4xx or 5xx range and a JSON body containing details of the error. This JSON body has two fields; error, containing a string indicating the error type and error containing an implementation-defined string containing a human readable description of the kind of error that occured.

The following table lists each error code, its associated HTTP status, JSON status value, and gives a non-normative description of the error. The error response data for a particular error code is the values of the HTTP Status and JSON Status columns for the row corresponding to that error code.

Error Code HTTP Status JSON Status Description
element not selectable 400 element not selectable An attempt was made to select an element that cannot be selected.
element not visible 400 element not visible An element command could not be completed because the element is not visible on the page.
invalid argument 400 invalid argument The arguments passed to a command are either invalid or malformed.
invalid cookie domain 400 invalid cookie domain An illegal attempt was made to set a cookie under a different domain than the current page.
invalid element coordinates 400 invalid element coordinates The coordinates provided to an interactions operation are invalid.
invalid element state 400 invalid element state An element command could not be completed because the element is in an invalid state (e.g. attempting to click an element that is no longer attached to the Document).
invalid selector 400 invalid selector Argument was an invalid selector.
invalid session id 404 invalid session id The session with the session id does not exist. This could be either from the session being quit or the session id passed in is not currently active.
javascript error 500 javascript error An error occurred while executing user supplied JavaScript.
move target out of bounds 500 move target out of bounds The target for mouse interaction is not in the browser's viewport and cannot be brought into that viewport.
no such alert 400 no such alert An attempt was made to operate on a modal dialog when one was not open.
no such element 404 no such element An element could not be located on the page using the given search parameters.
no such frame 400 no such frame A request to switch to a frame could not be satisfied because the frame could not be found.
no such window 400 no such window A request to switch to a different window could not be satisfied because the window could not be found.
script timeout 408 script timeout A script did not complete before its timeout expired.
session not created 500 session not created A new session could not be created.
stale element reference 400 stale element reference An element command failed because the referenced element is no longer attached to the Document.
timeout 408 timeout An operation did not complete before its timeout expired.
unable to set cookie 500 unable to set cookie A request to set a cookie's value could not be satisfied.
unexpected alert open 500 Unexpected alert open A modal dialog was open, blocking this operation.
unknown command 404 unknown command A command could not be executed because the remote end is not aware of it.
unknown error 500 unknown error An unknown error occurred in the remote end while processing the command.
unknown method 405 unknown command The requested command matched a known URL but did not match an method for that URL.
unsupported operation 500 unsupported operation Indicates that a command that should have executed properly cannot be supported for some reason.

Handling of Status Codes at the Local End

Status codes are returned from the remote end to the local end. The local end SHOULD convert these into a form appropriate for the implementation language. For example, in C the status codes might be converted to constant integer values, whereas in Java various exceptions could be thrown.

Implementations of the local end written in languages that support exceptions SHOULD make use of an exception hierarchy rooted on a WebDriverException (or similarly named base exception class). Where references to WebDriverException are made in this specification, we are referring to this local end conversion of status codes to local end exceptions.

The reason for this is to allow users of the local end to easily handle the all expected failure modes of a local WebDriver implementation by catching the WebDriverException.

It is strongly recommended that the WebDriverException contain as much diagnostic information as possible, including version numbers and details about the remote end. This is because experience suggests that when reporting errors from tests using WebDriver, users will simply cut-and-paste a stack trace of an exception. Adding this information to the exception makes the task of debugging problems considerably easier.

Sessions

Non-normative summary: A session is equivalent to a single instantiation of a particular user agent, including all its child browsers. WebDriver gives each session a unique session ID that can be used to differentiate one session from another, allowing multiple user agents to be controlled on the same machine if needed, and allowing sessions to be routed via a multiplexer (known as an intermediary node).

This requires the remote end to maintain global state of current active sessions, as well as the current session that only lasts for the duration of that session.

A WebDriver session represents the connection between a local end and a specific remote end. A remote end that is not an intermediary node must have at most one active session at a given time.

The session is set up at the invocation of a new session, and torn down at some later point; either explicitly by invoking quit, or implicitly when close is called at the last remaining top level browsing context.

A remote end has an associated list of active sessions, which is a list of all sessions that are currently started.

A remote end has an associated current session that is the session that is active for the duration of a command.

A remote end has an associated maximum active sessions (an integer) that defines the number of current active sessions that are supported. This may be "unlimited" for intermediary nodes, but must be exactly one for a final remote end.

A session has an associated session ID (a UUID) used to uniquely identify this session. Unless stated otherwise it is null.

A session has an associated active browsing context (a reference to top level browsing context) that indicates what browsing context commands are executed against.

A session has an associated script timeout that specifies a time to wait for scripts to run. Unless stated otherwise it is 30,000 milliseconds (30 seconds).

A session has an associated page load timeout that specifies a time to wait for the page loading to complete. Unless stated otherwise it is 300,000 milliseconds (five minutes).

A session has an associated implicit wait timeout that specifies a time to wait for the implicit element location strategy when locating elements using find element and find elements. Unless stated otherwise it is zero milliseconds.

A session has an associated page loading strategy, which is one of none, normal, and eager. Unless stated otherwise, it is normal.

Non-normative: A session is started when new session is invoked. It is an error to send any commands before starting a session, or to continue to send commands after the session has been. Maintaining session continuity between requests to the remote end requires passing a session ID.

newSession()

HTTP Method Path Template Notes
POST /session

The process for successfully creating a session MUST be:

  1. The local end creates a new Capabilities instance describing the desired capabilities for the session. The Capabilities object MUST be defined but MAY be empty.
  2. The local end MUST populate parameters with an object containing an entry named "desiredCapabilities" with the value set to the Capabilities instance from the previous step. An optional "requiredCapabilities" entry MAY also be created and populated with a Capabilities instance. The "sessionId" fields SHOULD be left empty.
  3. The remote end MUST examine the "requiredCapabilities" parameter if specified, SHOULD examine the "desiredCapabilities" parameter, and MUST create a new session matching as many of the Capabilities as possible. How the new session is created depends on the implementation of this specification.
    • If any of the "requiredCapabilities" cannot be fulfilled by the new session, the remote end MUST quit the session and return the session not created error code. The sessionId MUST be left as the default value unless one was set in the initial request, in which case that value MUST be used. The error message SHOULD list all unmet required capabilities though only a single required capability MUST be given.
    • If a capability is listed in both the requiredCapabilities and desiredCapabilities, the value in the requiredCapabilities MUST be used.
  4. The session MUST be assigned a sessionId which MUST be unique for each session (a UUID SHOULD be used). Generating the sessionId MAY occur before the session is created. If the parameters object had the "sessionId" key with a value, this MAY be discarded in favour of the freshly generated sessionId. Because of this, it is recommended that sessionId generation be done on the remote end. If the sessionId has already been used, a Response MUST be sent with the status code set to session not created and the value being an explanation that the sessionId has previously been used.
  5. The remote end MUST then return the session id, with the following fields MUST be set to:
    • "sessionId": the sessionId associated with this session.
    • "value": a Capabilities instance. The keys of this Capabilities instance MUST be the strings given in each of the supported Capabilities as defined in the relevant sections of this specification. Supported functionality MUST be included in this Capabilities instance, while unsupported functionality MAY be omitted.
    • "status": the success error code.

As stated, when returning the value of the Response, the remote end MUST include the capability names and values of all supported Capabilities from this specification. They MAY also include any additional capability names and values of supported Capabilities implemented independently of this specification. Local ends MAY choose to ignore this additional information. Intermediate nodes between the local and remote ends MAY interpret the Capabilities being returned.

If the browserName is given as a desired capability and omitted from the required capabilities, and the returned browserName value does not match the requested one, local ends SHOULD issue a warning to the user. How this warning is issued is undefined, but one implementation could be a log message. In this particular case, local ends MAY chose to change the Response's status code to session not created, and modify the value to explain the cause, including the value originally returned as the browserName capability. If this is done, the local end MUST ensure that the remote end quits the session.

Capability Names

The following keys SHOULD be used in the Capabilities instances. They all default to the null string.

browserName
The name of the desired browser as a string.
browserVersion
The version number of the browser, given as a string.
platformName
The OS that the browser is running on, matching any of the platform names given below.
platformVersion
The version of the OS that the browser is running on as a string.

Platform Names

The following platform names are defined and MUST be used, case sensitively, for the "platformName" unless the actual platform being used is not given in this list:

  • android
  • ios
  • linux
  • mac
  • unix
  • windows

In addition "any" MAY be used to indicate the underlying OS is either unknown or does not matter.

Implementors MAY add additional platform names. Until these are standardized, these MUST follow the conventions outlined in extending the protocol section with the exception that the vendor prefix SHOULD omit the leading "-" character.

For example, Mozilla's Firefox OS could be described as either "-MOZ-FIREFOXOS". The latter makes it easier for local ends to specify an enum of supported platforms and is therefore recommended in this case.

Error Handling

The following status codes MUST be returned by the "newSession" command:

success
The session was successfully created. The "value" field of the Response MUST contain a Capabilities object describing the session.
timeout
The new session could not be created within the time allowed for command execution on the remote end. This time MAY be infinite (in which case this status won't be seen). The "value" field of the Response SHOULD contain a string explaining that a timeout has occurred, but it MAY be left as the null value or filled with the empty string.
unknown error
An unhandled error of some sort has occurred. The "value" field of the Response SHOULD contain a more detailed description of the error as a string.

Remote End Matching of Capabilities

This section is non-normative.

The suggested order for comparing keys in the Capabilities instance when creating a session is:

  1. browserName
  2. browserVersion
  3. platformName
  4. platformVersion

For all comparisons, if the key is missing (as determined by a call to Capability.has() returning "false"), that particular criteria shall not factor into the comparison.

Removing a Session

HTTP Method Path Template Notes
DELETE /session/{sessionId}

When removing the session the User Agent MUST do the following

  1. If the sessionId does not exist an unsupported operation will be returned.
  2. close all top level browsing context that have the sessionId associated with it.
  3. set sessionId to null.

Navigation

Introduction

Almost all usages of the WebDriver API begin by navigating to a particular URL. This section not only describes the commands used for navigation, but also describes when commands must be processed.

The Page Load Strategy

Local ends may choose at what point during the page load cycle the remote end returns a response to navigation commands by requesting a particular page load strategy when creating a new session. The available page load strategies are:

normal

The response is sent when the document.readyState of the frame currently handling commands equals complete.

eager

The response is sent when the document.readyState of frame currently handling reaches interactive or complete.

none

The response is sent immediately after initiating the navigation.

All WebDriver implementations MUST support the normal and eager modes and SHOULD support the none mode. If no page loading strategy is chosen, then normal MUST be the default. In addition, implementors MAY add additional page loading strategies.

get

HTTP Method Path Template Notes
POST /session/{sessionId}/url

The get command is used to cause the browser to navigate to a new location. From a user's point of view, it is as if they have entered the "url" into the URL bar.

The remote end steps for the get command are:

  1. If the current browsing context is no longer open, return an error with code no such window.

  2. Let url be the result of getting a property named "url" from the parameters argument.

  3. If url is undefined, return an error with code invalid argument

  4. Navigate the current browsing context's to url. If this navigation results in a HTTP 401 response, the remote end must proceed with the steps below, irrespective of how the authentication challenge is handled.

  5. If the current session's page load strategy is none jump to the next step in this overall set of steps. Otherwise:

    1. Let readiness target be "interactive" if the current session's page load strategy is eager, or "complete" if it is normal.

    2. Wait for the current document readiness to reach readiness target, or for the current session's load timeout milliseconds to pass, whichever occurs sooner.

    3. If the previous step completed by the load timeout being reached, and the browser is not currently displaying an alert, return an error with code timeout.

  6. Return success with data null

getCurrentUrl()

HTTP Method Path Template Notes
GET /session/{sessionId}/url

WebDriver implementations MUST allow the users to be able to get the current URL. In the case of a Nested Browsing Context WebDriver MUST return the URL of the [[html51]] top level browsing context. It is the equivalent to returning document.location.href for the [[html51]] top level browsing context.

If the page takes too long as specified by the timeouts a timeout error MUST be raised. If the top level browsing context currently receiving commands is no longer open a no such window error MUST be raised.

goBack()

HTTP Method Path Template Notes
POST /session/{sessionId}/back

The "goBack" command is equivalent to a user hitting the "back" button in their browser, and MUST behave as a traversal of the browser history by a delta of -1 (as defined in [[!html51]]). If a user calls "goBack" when there are no further pages in the browser's history stack, then this call MUST be a no-op.

If the page takes too long as specified by the timeouts a timeout error MUST be raised. If the top level browsing context currently receiving commands is no longer open a no such window error MUST be raised.

goForward()

HTTP Method Path Template Notes
POST /session/{sessionId}/forward

The "goForward" command is equivalent to a user hitting the "forward" button in their browser, and MUST behave as a traversal of the browser history by a delta of +1 (as defined in [[!html51]]). If a user calls "goForward" when there are no further pages in the browser's history stack, then this call MUST be a no-op.

If the page takes too long as specified by the timeouts a timeout error MUST be raised. If the top level browsing context currently receiving commands is no longer open a no such window error MUST be raised.

refresh()

HTTP Method Path Template Notes
POST /session/{sessionId}/refresh

"refresh" emulates the user hitting the "refresh" or "reload" button in their browser, causing the current page to be reloaded.

If the page takes too long as specified by the timeouts a timeout error MUST be raised. If the top level browsing context currently receiving commands is no longer open a no such window error MUST be raised.

getTitle()

HTTP Method Path Template Notes
POST /session/{sessionId}/title

The "getTitle" command MUST return the contents of the <title> element like it would for document.title. In the case of a Nested Browsing Context WebDriver MUST return the title of the [[html51]] top level browsering context.

If the page takes too long as specified by the timeouts a timeout error MUST be raised. If the top level browsing context currently receiving commands is no longer open a no such window error MUST be raised.

Invalid SSL Certificates

Capability NameType
secureSslboolean

WebDriver implementations MUST support users accessing sites served via HTTPS. Access to those sites using self-signed or invalid certificates, and where the certificate does not match the serving domain MUST be the same as if the HTTPS was configured properly.

The reason for this is that implementations of this spec are often used for testing. It's a sorry fact that many QA engineers and testers are asked to verify that apps work on sites that have insecure HTTPS configurations

The exception to requirement is if the Capabilities used to initialize has the WebDriver session had the capability secureSsl set to true. In this case, implementations MAY choose to make accessing a site with bad HTTPS configurations cause a WebDriverException to be thrown. Remote end implementations MUST return an unknown error status in this case. If this is the case, the Capabilities describing the session MUST also set the secureSsl capability to "true".

Detecting When to Handle Commands

Commands MUST only be processed when the page loading strategy being used indicates that page loading is complete.

Commands SHOULD be handled in a synchronous fashion. Requests should be received and then a response sent when the Command has completed.

Controlling Windows

Definitions

Within this specification, a window equates to [[!html51]]'s top level browsing context. Put another way, within this spec browser tabs are counted as separate windows.

TODO: define "frame"

A Window Handow is an opaque string that MUST uniquely identify the top level browsing context and MUST NOT be "current". This MAY be a UUID.

Window Handles

getWindowHandle()

HTTP Method Path Template Notes
GET /session/{sessionId}/window_handle

Each top level browsing context has a window handle. The "getWindowHandle" command can be used to obtain the top level browsing context handle for the top level browsing context that commands are currently acting upon.

Iterating Over top level browsing context

getWindowHandles()

HTTP Method Path Template Notes
GET /session/{sessionId}/window_handles

This array of returned strings MUST contain a handle for every top level browsing context associated with the browser session and no others. For each returned window handle the javascript expression "window.top.closed" (or equivalent) MUST evaluate to false at the time the command is being executed.

The ordering of the sequence is not defined, but MAY be determined by iterating over each OS Window and returning the top level browsing context items within that OS window before iterating over the top level browsing contexts of the next OS window. For example, in the diagram below, the window handle should be returned as the handles for: win1tab1, win1tab2, win2.

Two top level windows. The first window has two tabs, lablled win1tab1 and win1tab2. The second window has only one tab labelled win2

This implies that the correct way to determine whether or not a particular interaction with the browser opens a new window is done by obtaining the set of window handle before the interaction is performed and comparing with the set after the action is performed.

Closing Windows

close()

HTTP Method Path Template Notes
DELETE /session/{sessionId}/window_handle

The close command closes the top level browsing context that Commands are currently being sent to. If this means that a call to get the list of window handles would return an empty list, then this close command MUST remove the session.

Once the top level browsing context has closed, future commands MUST return a status code of no such window until a new top level browsing context is selected for receiving commands.

Resizing and Positioning Windows

All commands MUST be handled by the OS window that ultimately owns the current context.

double height
The height of the top level browsing context in CSS reference pixels
.
double width
The width of the top level browsing context in CSS reference pixels
.

setWindowSize()

HTTP Method Path Template Notes
POST /session/{sessionId}/window/size

Resizes the OS window currently receiving commands to have the height and width passed in as parameters.

If a request is made to resize a OS window to a size which cannot be performed (e.g. the browser has a minimum, or fixed OS window size, or the operating system does not support resizing windows at all as is the case in many phone OSs), an unsupported operation status code MUST be returned.

After setWindowSize, the browser window MUST NOT be in the maximised state.

unsigned double width
The "width" value refer to the javascript window.outerwidth property. If the User Agent does not support this property, it represents the width of the whole OS window including window chrome and window resizing borders/handles.
unsigned double height
The "height" value refer to the javascript window.outerheight property. If the User Agent does not support this property, it represents the width of the whole OS window including window chrome and window resizing borders/handles.

getWindowSize()

HTTP Method Path Template Notes
GET /session/{sessionId}/window/size

A command named "getWindowSize()":

  1. Create a WindowSize dictionary containing the height and width keys.
  2. Populate width with the value of window.outerwidth property of the top level browsing context currently receiving commands in CSS reference pixels. If the User Agent does not support this property, it represents the width of the whole OS window including window chrome and window resizing borders/handles.
  3. Populate height with the value of window.outerheight property of the top level browsing context currently receiving commands in CSS reference pixels. If the User Agent does not support this property, it represents the width of the whole OS window including window chrome and window resizing borders/handles.
  4. Return WindowSize

maximizeWindow()

HTTP Method Path Template Notes
POST /session/{sessionId}/window/maximize

After maximizeWindow, the OS window currently receving commands MUST be left as if the maximise button had been pressed if, and only if, the window manager of the OS supports this concept; it is not sufficient to leave the window "restored", but with the full screen dimensions.

If a request is made to resize a window to a size which cannot be performed (e.g. the browser has a minimum, or fixed window size, or the operating system does not support resizing windows at all as is the case in many phone OSs), an unsupported operation status code MUST be returned.

fullscreenWindow()

After fullscreenWindow, the OS window currently receiving commands MUST be in full-screen mode. For those operating systems that support the concept, this MUST be equivalent to if the user requested the OS window be full screen.

If the User Agent or OS does not support switching to full-screen mode, an unsupported operation status code MUST be returned.

Context of Commands

Web applications can be composed of multiple top level browsing context and/or frames. For a normal user, the context in which an operation is performed is obvious: it's the window or frame that currently has OS focus and which has just received user input. The WebDriver API does not follow this convention. There is an expectation that many browsers using the WebDriver API may be used at the same time on the same machine. This section describes how WebDriver tracks which window or frame is currently the context in which commands are being executed.

Default Content

WebDriver's default content is [[!html51]]'s top level browsing context that is currently receiving WebDriver commands.

When a WebDriver instance is started and a single OS window is opened, the default content of that OS window is automatically selected for receiving further commands. If more than one OS window or multiple top level browsing contexts are opened when the session starts, then the user MUST first select which top level browsing context to act upon using the switchToWindow command. Until the user selects a top level browsing context, all commands must return a status code of no such window.

Switching Windows

switchToWindow()

DOMString handle
The identifier used for a top level browsing context

HTTP Method Path Template Notes
POST /session/{sessionId}/window

The "switchToWindow" command is used to select which top level browsing context MUST be used as the context for processing commands. In order to determine which top level browsing context should be used for accepting commands, the "switchToWindow" command MUST iterate over all top level browsing context comparing the window handle.

If no top level browsing contexts match, then a "no such window" status code MUST be returned, otherwise the "default content" of the first match will be selected for accepting commands.

Switching Frames

switchToFrame()

HTTP Method Path Template Notes
POST /session/{sessionId}/frame
WebElement or unsigned short? id
The identifier used for a frame.

The "switchToFrame" command is used to select which frame which is a child of thetop level browsing context MUST be used as the context for handling future commands. All frame switching is taken from the current context from which commands are currently being handled. The "id" parameter can be an unsigned short or a WebElement. WebDriver implementations MUST determine which frame to select using the following algorithm:

  1. If the "id" is a unsigned short the current context is set to the equivalent of the JS expression "window.frames[id]" where "id" is the number and "window" is the Document window represented by the current context.
  2. If the "id" is null, the current context is set to the default content.
  3. If the "id" represents a WebElement, and the corresponding Document element represents a FRAME or an IFRAME, and the WebElement is part of the current context, the "window" property of that Document element becomes the current context.

In all cases if no match is made a "no such frame" status code MUST be returned.

If the indicated frame exists, frame switching MUST succeed even if doing so would violate the normal security constraints in place within the Javascript sandbox.

switchToParentFrame()

HTTP Method Path Template Notes
POST /session/{sessionId}/frame/parent

The "switchToParentFrame" command MUST set the context of future commands to the window.parent. If the current context is the [[!html51]]'s top level browsing context, the context remains unchanged.

Running Without Window Focus

All browsers must comply with the focus section of the [[!html51]] spec. In particular, the requirement that the active element within a top-level browsing context be independent of whether or not the top-level browsing context itself has system focus MUST be followed.

This requirement is put in place to allow efficient machine utilization when using the WebDriver API to control several browsers independently on the same desktop

Elements

Conformance tests for this section can be found in the webdriver module under the "element_location" folder.

One of the key abstractions of the WebDriver API is the concept of a WebElement. A WebElement represents an Element as defined in the [[!DOM4]] specification. When communicating between the remote end and the local end this SHOULD be a UUID. Because the WebDriver API is designed to allow users to interact with apps as if they were actual users, the capabilities offered by the WebElement interface are somewhat different from those offered by the Document element interface.

Each WebElement instance must have a unique identifier, which is distinct from the value of the Document element "id" property. The identifier for every WebElement representing the same underlying Document element MUST be the same. The identifiers used to refer to different underlying Document elements MUST be unique within the session over the entire duration of the session.

This requirement around WebElement identifiers allows for efficient equality checks when the WebDriver API is being used out of process.

Finding Elements in a document

When the findElement() or findElements() WebDriver Command is called the following must be parameters after the local end has made a request to the remote end:

  1. let using contain the Element Location Strategy. If it is not a valid stategy:
    • Set the HTTP Response status code to 500
    • Let status be equal to Invalid Selector
    • Let value to a stating that the strategy is invalid. It may return a list of valid search strategies.
  2. let value contain a string that will be passed to the Element Location Strategy call. If value is an empty string or null:
    • Set the HTTP Response status code to 500
    • Let status be equal to Invalid Selector
    • Let value to a stating that the strategy is invalid. It may return a list of valid search strategies.
  3. Call the relevant Element Location Strategy and return what is described in findElement() or findElements() WebDriver Command described below.

findElements()

When there is a need to find multiple elements on a document that we can return to the local end we use the following algorithm:

HTTP Method Path Template Notes
POST /session/{sessionId}/elements
  1. Let result be equal to an empty list
  2. Let queryResult be a NodeList returned from Element Location Strategy
  3. Repeat for every value in queryResult if not an empty set else return result
    1. Let id be the unique identifier for the DOMElement.
    2. Append {"element-6066-11e4-a52e-4f735466cecf": id} to result
  4. return result. The object returned will look like the following:
                  {
                    "value": [{"element-6066-11e4-a52e-4f735466cecf": id}, {"element-6066-11e4-a52e-4f735466cecf": id}]
                  }
                

When there is a need to search from an element to find the next WebElements we use the following algorithm:

HTTP Method Path Template Notes
POST /session/{sessionId}/element/{ELEMENT}/elements
  1. Let result be equal to an empty list.
  2. Let element be the start node for the query in the Element Location Strategy
  3. Let queryResult be a NodeList returned from Element Location Strategy
  4. Repeat for every value in queryResult if not an empty set else return result
    1. Let id be the unique identifier for the DOMElement.
    2. Append {"element-6066-11e4-a52e-4f735466cecf": id} to result
  5. return result. The object returned will look like the following:
                  {
                    "value": [{"element-6066-11e4-a52e-4f735466cecf": id}, {"element-6066-11e4-a52e-4f735466cecf": id}]
                  }
                

findElement()

HTTP Method Path Template Notes
POST /session/{sessionId}/element
  1. Let id be an identifier for a DOMElement returned from Element Location Strategy. If a NodeList is returned, the first element in the NodeList MUST be used.

    If id is empty:

    • Let the HTTP response status code be 501
    • let status contain the error no such element
    • let value contain the details of the search contained in using and value above.

    If an error is returned from Element Location Strategy do the following.(todo describe how the error is returned)

    • Let the HTTP response status code be 501
    • let status contain the error invalid selector
    • let value contain the details of the search contained in using and value above.

  2. Let result be equal to {"element-6066-11e4-a52e-4f735466cecf": id}
  3. return result. The object returned will look like the following:
                  {
                    "value": {"element-6066-11e4-a52e-4f735466cecf": id}
                  }
                

When searching from an element from another element the following algorithm should be used:

HTTP Method Path Template Notes
POST /session/{sessionId}/element/{ELEMENT}/element
  1. Let element be the start node for the query in the Element Location Strategy
  2. Let id be a unique identifier for the DOMElement returned from Element Location Strategy. If a NodeList is returned, the first DOMElement in the NodeList MUST be used.

    If id is empty:

    • Let the HTTP response status code be 501
    • let status contain the error no such element
    • let value contain the details of the search contained in using and value above.

    If an error is returned from Element Location Strategy do the following.(todo describe how the error is returned)

    • Let the HTTP response status code be 501
    • let status contain the error invalid selector
    • let value contain the details of the search contained in using and value above.

  3. Let result be equal to {"element-6066-11e4-a52e-4f735466cecf": id}
  4. return result. The object returned will look like the following:
                  {
                    "value": {"element-6066-11e4-a52e-4f735466cecf": id}
                  }
                

getActiveElement()

To get the currently active element on the document do the following algorithm:

HTTP Method Path Template Notes
POST /session/{sessionId}/element/active
  1. Let element be a DOMElement that is returned from calling document.activeElement
  2. Let id be the unique identifier for the DOMElement which represents element. If element does not have a unique identifier then one should be generated and stored.
  3. Let result be equal to {"element-6066-11e4-a52e-4f735466cecf": id}
  4. return result. The object returned will look like the following:
                  {
                    "value": {"element-6066-11e4-a52e-4f735466cecf": id}
                  }
                

Element Location Strategies

All element location strategies MUST return elements in the order in which they appear in the current document.

CSS Selectors

Strategy name: css selector

If a browser supports the CSS Selectors API ([[!SELECTORS-API]]) it MUST support locating elements by CSS Selector. If the browser does not support the browser CSS Selector spec it MAY choose to implement locating by this mechanism. If the browser can support locating elements by CSS Selector, it MUST set the "cssSelector" capability to boolean true when responding to the newSession(). Elements MUST be returned in the same order as if "querySelectorAll" had been called with the Locator's value. Compound selectors are allowed.

ECMAScript

Finding elements by ecmascript is covered in the ecmascript part of this spec.

Link Text

Strategy name: link text

This strategy MUST be supported by all WebDriver implementations.

This strategy MUST return all "a" elements with visible text exactly and case sensitively equal to the term being searched for.

This is equivalent to:

		  elements = driver.find_elements(by = By.TAG_NAME, value = "a")
		  result = []
		  for element in elements:
		    text = element.text
		    if text == search_term:
		      result.append(element)
		

Where "search_term" is the link text being searched for, and "result" contains the list of elements to return.

Partial Link Text

Strategy name: partial link text

This strategy MUST be supported by all WebDriver implementations.

This strategy is very similar to link text, but rather than matching the entire string, only a subset needs to match. That is, this MUST return all "a" elements with visible text that partially or completely and case sensitively matches the term being searched for.

This is equivalent to:

		  elements = driver.find_elements(by = By.TAG_NAME, value = "a")
		  result = []
		  for element in elements:
		    text = element.text
		    if text.search(seach_term) != -1:
		      result.append(element)
		

Where "search_term" is the link text being searched for, and "result" contains the list of elements to return.

XPath

Strategy name: xpath

All WebDriver implementations MUST support finding elements by XPath 1.0 [[!XPATH]] with the edits from section 3.3 of the [[!html51]] specification made. If no native support is present in the browser, a pure JS implementation MAY be used. When called, the returned values MUST be equivalent of calling "evaluate" function from [[DOM-LEVEL-3-XPATH]] with the result type set to "ORDERED_NODE_SNAPSHOT_TYPE (7).

Element Displayedness

The visibility of a Document element is guided by what is perceptually visible to the human eye. An element's displayedness does in this context thus not relate in any way to the visibility or display style properties [[!CSS3BOX]].

The approach used by WebDriver to ascertain an element's visibility is based on crude approximations about the element's nature and relationship in the tree. An element is in general to be considered visible if any part of it is drawn on the canvas within the bounderies of the viewport.

The element displayed algorithm is a boolean state where true signifies that the element is displayed and false not displayed. To compute the state on element:

  1. If the attribute hidden is set, return false.
  2. If the computed value of the display style property is "none", return false.
  3. If it has a [[!CSS3-2D-TRANSFORMS]] or [[!CSS3-3D-TRANSFORMS]] style property that gives a negative X or Y coordinates to the canvas, return false.
  4. If element is the document's root element, that is document.documentElement:
    1. If the computed value of the background-color property is "transparent", run these substeps:
      1. If element is an HTML HTML element [[!html51]], and the computed value of the background-color style property of the first BODY element descendant of the element in tree order, relative to that element, is also "transparent", return false.
      2. Otherwise return false.
  5. If element is an option or optgroup element, and element's parent node is a select element:
    1. Apply the element displayed algorithm on element's parent node.
    2. If the return value is false, abort these steps and return that value.
  6. If element is a map element, run these substeps:
    1. Let any images visible be a boolean initially set to false.
    2. For each img element, image element in the document with a name attribute matching the value of element's usemap attribute, run these substeps:
      1. Run the element displayed algorithm on image element and set any images visible to any images visible bitwise OR its return value.
    3. If any images visible is true, abort these steps and return its value.
  7. If element is an area element:
    1. For each ancestral element parent, in tree order, run the following substeps:
      1. If parent is a map element, apply the element displayed algorithm on it.
      2. If the return value is false, abort these steps and return that value.
      3. Otherwise apply step 7.1 on parent.
  8. If element is a [[!DOM4]] text node, return true.
  9. If it has equal to or more than one direct descendant elements:
    1. Let visible children be a boolean initially set to false.
    2. For each descendant element child, in tree order, run the following substeps:
      1. Let rectangle be the DOMRect returned by calling getBoundingClientRect on child.
      2. If the value of the height property of rectangle is greater than zero CSS pixels, and the value of the width property of rectangle is greater than zero CSS pixels:
        1. Set visible children to visible children bitwise OR true.
  10. For each ancestral element parent, in tree order, run the following substeps:
    1. Apply the element displayed algorithm to parent.
    2. If the return value is false, abort these steps and return that value.
    3. If parent is a block element box and the computed values of either overflow-x or overflow-y is "hidden":
      1. Let parent dimensions be the DOMRect that is the first element of the DOMRectList array returned by calling getClientRects on parent.
      2. Let element dimensions be the DOMRect that is the first element of the DOMRectList array returned by calling getClientRects on element.
      3. Let parent style be the computed style of parent.
      4. Return false if any the following conditions evaluate to false:
      5. Run step 10 on the parent elements of parent, if any.
  11. Return true.

If the steps above return true, then the element MUST also be interactable should it meet the other criteria for being interactable. If any part of the BODY can be brought into the current viewport, the return value MUST be true.

Element State

Reading current element state from the document

Conformance tests for this section can be found in the webdriver module under the "element_state" folder.

When we are returning an ElementRect to the local end it will need to be serialised

double x
The x coordinate for the top left of the element
double y
The y coordinate for the top left of the element
double height
Height of the element in CSS reference pixels
double width
Width of the element in CSS reference pixels

isDisplayed()

HTTP Method Path Template Notes
GET /session/{sessionId}/element/{element}/displayed

The command is used to determine the element displayedness of the Document element connected with the web element reference given by the element fragment in the path.

The response is composed using the following algorithm:

  1. Let response be an initially empty response.
  2. Let visible be a boolean initially set to false.
  3. Let element be an initially undefined Document element.
  4. Let element reference be a string with the value of the element fragment from the path.
  5. If element reference is null or has a length equal to 0, set response's status to the invalid argument status and return response.
  6. If the default content's top level browsing context is no longer open, set response's status to the no such window status and return response.
  7. Set element be the Document element found after applying the web element lookup algorithm to the element reference map.
  8. If element is null or element does not represent a Document element, set response's status to the no such element status and return response.
  9. If element represents Document element that is no longer attached to the document's node tree, set response's status to the stale element reference status and return response.
  10. Apply the element displayed algorithm to element and set visible to its return value.
  11. Set response's status to success and its value to visible.
  12. Return response.

isSelected()

HTTP Method Path Template Notes
GET /session/{sessionId}/element/{ELEMENT}/selected

The remote end MUST determine whether a WebElement is selected using the following algorithm:

  1. If the item is not "selectable", the WebElement is not selected. A selectable element is either an OPTION element or an INPUT element of type "checkbox" or "radio".
  2. If the Document node represented by the WebElement is an OPTION element, the "selectedness" of the element, as defined in [[!html51]] determines whether the element is selected.
  3. Otherwise, the value of the Document node's "checked" property determines whether the element is selected. This MUST reflect the element's "checkedness" as defined in [[!html51]].

If ELEMENT does not represent a Document element, or it represents a Document element that is no longer attached to the document's node tree, then the WebDriver implementation MUST immediately abort the command and return a stale element reference error. If the top level browsing context currently receiving commands is no longer open a no such window error MUST be raised.

getElementAttribute()

HTTP Method Path Template Notes
GET /session/{sessionId}/element/{ELEMENT}/attribute/{name}

Although the [[!html51]] spec is very clear about the difference between the properties and attributes of a Document element, users are frequently confused between the two. Because of thisend point which covers the case of returning either of the value of a Document element property or attribute. If a user wishes to refer specifically to an attribute or a property, they should evaluate Javascript in order to be unambiguous.

The end result of this algorithm are values that can be passed to other commands within this specification. Notably, this means that URLs that are returned can be passed to get and the expected URL will be navigated to.

To determine the value of the response, the following steps must be taken where name is the name property on the parameters dictionary in Command, and element is the Document element modeled by the ELEMENT parameter.:

  1. Initially set result to null.
  2. Handle special-cases:
    1. If "name" case insensitively matches "style", then store the value of the computed value of the style property of element, serialized as defined in the [[!CSSOM-VIEW]] spec, as result. Notably, CSS property names must be cased as specified in in section 6.5.1 of the [[!CSSOM-VIEW]] spec. In addition, color property values must be standardized to RGBA color format as described in [[!css3-color]]. If a user agent does not support RGBA then it MUST return a value as 1 for opacity.
    2. If "name" case insensitively matches "selected" or "checked", and the element is selectable:
      1. If the element supports neither a selectedness or checkedness check, then store null as result.
      2. For an option element, store the element's selectedness as result.
      3. In all other cases, store the element's checkedness as result.
    3. If any of the above steps have been executed, go to the result coercion step of this algorithm.
  3. Obtain the property indexed by "name" from the element and store this as result. If name case insensitively matches "class" set result to be element's className property. Similarly, if name case insensitively matches "readonly", set result to be the element's readOnly property.
  4. If result is null or undefined, or if it is an object, set the value of result to be the value of the Attr node obtained by calling getAttributeNode on element iff that Attr is specified. That is, result is the equivalent of executing the following Ecmascript: var attr = element.getAttributeNode(name); var result = (attr && attr.specified) ? attr.value : null;
  5. Coerce the return value to a DOMString:
    1. If result is a boolean value, use the value "true" if result is true, or null otherwise.
    2. if result is null or undefined, set result to be null.
    3. In all other cases, coerce result to a DOMString.
DOMString name
The name of the property or attribute to return.

If the ELEMENT does not represent a Document element, or it represents a Document element that is no longer attached to the document's node tree, then the WebDriver implementation MUST immediately abort the command and return a stale element reference error. If the top level browsing context currently receiving commands is no longer open a no such window error MUST be raised.

getCssValue()

HTTP Method Path Template Notes
GET /session/{sessionId}/element/{ELEMENT}/css/{propertyName}

The "getCssValue" command will return a DOMString of the value of the property passed. It MUST return the value of getPropertyValue(propertyName) returned from calling window.getComputedStyle(element). Color property values MUST be standardized to RGBA color format as described in [[!css3-color]]. If a user agent does not support RGBA then it MUST return a value as 1 for opacity. If the property is not present then return an empty string.

DOMString propertyName
The name of the property whose value will be returned

If the ELEMENT does not represent a Document element, or it represents a Document element that is no longer attached to the document's node tree, then the WebDriver implementation MUST immediately abort the command and return a stale element reference error. If the top level browsing context currently receiving commands is no longer open a no such window error MUST be raised.

getElementText()

HTTP Method Path Template Notes
GET /session/{sessionId}/element/{ELEMENT}/text

The following definitions are used in this section:

Whitespace
Any text that matches the ECMAScript regular expression class \s.
Whitespace excluding non-breaking spaces
Any text that matches the ECMAScript regular expression [^\S\xa0]
Block level element
A block-level element is one which is not a table cell, and whose effective CSS display style is not in the set ['inline', 'inline-block', 'inline-table', 'none', 'table-cell', 'table-column', 'table-column-group']
Horizontal whitespace characters
Horizontal whitespace characters are defined by the ECMAScript regular expression [\x20\t\u2028\u2029].

The expected return value is roughly what a text-only browser would display. The algorithm for determining this text is as follows:

Let lines equal an empty array. Then:

  1. if the element is in the head element of the document, return an empty string otherwise carry on with the algorithm below.
  2. For each descendent of node, at time of execution, in order:
    1. Get whitespace, text-transform, and then, if descendent is:
      • a node which is not displayed, do nothing
      • a [[!DOM4]] text node let text equal the nodeValue property of descendent. Then:
        1. Remove any zero-width spaces (\u200b, \u200e, \u200f), form feeds (\f) or vertical tab feeds (\v) from text.
        2. Canonicalize any recognized single newline sequence in text to a single newline (greedily matching (\r\n|\r|\n) to a single \n)
        3. If the parent's effective CSS whitespace style is 'normal' or 'nowrap' replace each newline (\n) in text with a single space character (\x20). If the parent's effective CSS whitespace style is 'pre' or 'pre-wrap' replace each horizontal whitespace character with a non-breaking space character (\xa0). Otherwise replace each sequence of horizontal whitespace characters except non-breaking spaces (\xa0) with a single space character
        4. Apply the parent's effective CSS text-transform style as per the CSS 2.1 specification ([[!CSS21]])
        5. If last(lines) ends with a space character and text starts with a space character, trim the first character of text.
        6. Append text to last(lines) in-place
      • an element which is displayed. If the element is a:
        • BR element: Push '' to lines and continue
        • Block-level element and if last(lines) is not '', push '' to lines.
        And then recurse depth-first to step 1 at the beginning of the algorithm with descendent set to the current element
      • If element is a TD element, or the effective CSS display style is 'table-cell', and last(lines) is not '', and last(lines) does not end with whitespace append a single space character to last(lines) [Note: Most innerText implementations append a \t here]
      • If element is a block-level element: push '' to lines
  3. The string MUST then have the white space normalised as defined in the [[!XPATH]] normalize-space function which is then returned.

If the ELEMENT does not represent a Document element, or it represents a Document element that is no longer attached to the document's node tree, then the WebDriver implementation MUST immediately abort the command and return a stale element reference error. If the top level browsing context currently receiving commands is no longer open a no such window error MUST be raised.

getElementTagName()

HTTP Method Path Template Notes
GET /session/{sessionId}/element/{ELEMENT}/name

The "getElementTagName" command will return a DOMString that is the qualified name of the element.

If the ELEMENT does not represent a Document element, or it represents a Document element that is no longer attached to the document's node tree, then the WebDriver implementation MUST immediately abort the command and return a stale element reference error. If the top level browsing context currently receiving commands is no longer open a no such window error MUST be raised.

ElementRect getElementRect()

HTTP Method Path Template Notes
GET /session/{sessionId}/element/{ELEMENT}/rect

The "getElementRect" command MUST return the ElementRect with:

  • x and y represent the top left coordinates of the WebElement relative to top left corner of the document.
  • height and the width will contain the height and the width of the DOMRect of the WebElement.

The point (0, 0) refers to the top left corner of the document.

If the ELEMENT does not represent a Document element, or it represents a Document element that is no longer attached to the document node tree, then the WebDriver implementation MUST immediately abort the command and return a stale element reference error. If the top level browsing context currently receiving commands is no longer open a no such window error MUST be raised.

isEnabled()

HTTP Method Path Template Notes
GET /session/{sessionId}/element/{ELEMENT}/enabled

The "isEnabled" command MUST return false if all the following criteria are met otherwise return true:

If the ELEMENT does not represent a Document element, or it represents a Document element that is no longer attached to the document node tree, then the WebDriver implementation MUST immediately abort the command and return a stale element reference error. If the top level browsing context currently receiving commands is no longer open a no such window error MUST be raised.

Executing Javascript

Open questions: What happens if a user's JS triggers a modal dialog? Blocking seems like a reasonable idea, but there is an assumption that WebDriver is not threadsafe. What happens to unhandled JS errors? Caused by a user's JS? Caused by JS on a page? How does a user of the API obtain the list of errors? Is that list cleared upon read?

Conformance tests for this section can be found in the webdriver module under the "ecmascript" folder.

Javascript Command Parameters

When calling Synchronous JavaScript Execution or calling Asynchronous JavaScript Execution we need to extract the following from payload body into JavaScript Command Parameters:

When executing Javascript, it MUST be possible to reference the args parameter using the function's arguments object. The arguments MUST be in the same order as defined in args. Each WebDriver implementation MUST preprocess the values in args using the following algorithm:

For each index, index in args, if args[index] is...

  1. a long, boolean, DOMString, or null, then let args[index] = args[index].
  2. a sequence, then recursively apply this algorithm to args[index] and assign the result to args[index].
  3. an object, then recursively apply this algorithm to each value in args[index] and assign the result to args[index].
  4. a WebElement, then:
    1. If ELEMENT does not represent a Document element, or it represents a Document element that is no longer attached to the document's tree, then the WebDriver implementation MUST immediately abort the command and return a stale element reference error.
    2. Otherwise, let args[index] be the underlying Document element.
  5. Otherwise WebDriver implementations MAY throw an unknown error indicating the index of the unhandled parameter but SHOULD attempt to convert the value into a object.

Synchronous Javascript Execution

executeScript()

DOMString script
The script to execute.
sequence<Argument>? args
The script arguments.

HTTP Method Path Template Notes
POST /session/{sessionId}/execute

When executing JavaScript, the WebDriver implementations MUST use the following algorithm:

  1. Let window be the Window object for WebDriver's current command context.
  2. Let script be the DOMString from the command's script parameter.
  3. Let fn be the Function object created by executing new Function(script);
  4. Let args be the sequence created by the pre-processing algorithm defined above.
  5. Invoke fn.apply(window, args);
  6. If the previous step errors then:
    1. Let error be the thrown value.
    2. Set the response status to javascript error.
    3. Set the response value to a object, dict.
    4. If error is an Error, then set a "message" entry in dict whose value is the DOMString defined by error.message.
    5. Otherwise, set a "message" entry in dict whose value is the DOMString representation of error.
  7. Otherwise:
    1. Let result be the value returned by the function in step #5.
    2. Set the command's response status to success.
    3. Let value be the result of the following algorithm:
      1. If result is:
        1. undefined or null, return null.
        2. a long, boolean, or DOMString, return result.
        3. a Document element, then return the corresponding WebElement for that Document element.
        4. a Sequence <Node> nodes, then return the result of recursively applying this algorithm to result.
        5. an object, then return the object created by recursively applying this algorithm to each property in result.
    4. Set the response value to value.
  8. Return the response.

Asynchronous Javascript Execution

executeAsyncScript()

DOMString script
The script to execute.
sequence<Argument>? args
The script arguments.

HTTP Method Path Template Notes
POST /session/{sessionId}/execute_async

When executing asynchronous JavaScript, the WebDriver implementation MUST use the following algorithm:

  1. Let timeout be the value of the last "script" timeout command, or 0 if no such commands have been received.
  2. Let window be the Window object for WebDriver's current command context.
  3. Let script be the DOMString from the command's script parameter.
  4. Let fn be the Function object created by executing new Function(script);
  5. Let args be the sequence created by the pre-processing algorithm defined above.
  6. Let callback be a Function object pushed to the end of args.
  7. Register a one-shot timer on window set to fire timeout milliseconds in the future.
  8. Invoke fn.apply(window, args);
  9. If the previous step errors then:
    1. Let error be the thrown value.
    2. Set the response status to javascript error.
    3. Set the response value to a object, dict.
    4. If error is an Error, then set a "message" entry in dict whose value is the DOMString defined by error.message.
    5. Otherwise, set a "message" entry in dict whose value is the DOMString representation of error.
  10. Otherwise, the WebDriver implementation MUST wait for one of the following to occur:
    1. if the one-shot timer that was set on the window fires , the WebDriver implementation MUST immediately set the response status to timeout and return.
    2. if the window fires an unload event, the WebDriver implementation MUST immediately set the response status to JavascriptError and return with the error message set to "Javascript execution context no longer exists.".
    3. if the callback function is invoked, then:
      1. Let result be the first argument passed to callback.
      2. Set the command's response status to Success.
      3. Let value be the result of the following algorithm:
        1. If result is:
          1. undefined or null, return null.
          2. a long, boolean, or DOMString, return result.
          3. a Document element, then return the corresponding WebElement for that Document element.
          4. a Sequence <Node> Nodes, then return the result by recursively applying this algorithm to result. WebDriver implementations SHOULD limit the recursion depth.
          5. an object, then return the object created by recursively applying this algorithm to each property in result.
      4. Set the command's response value to value.
    4. Return the response.

Reporting Errors

Cookies

This section describes the interaction with cookies as described in the HTML Specification ([[!html51]]). When retrieving and setting a cookie it MUST be in the format of a Cookie.

Conformance tests for this section can be found in the webdriver module under the "cookies" folder.

Cookie

When returning Cookie objects, the server SHOULD include all optional fields it is capable of providing the information for.

getCookie

HTTP Method Path Template Notes
GET
HTTP Method Path Template Notes
GET

The remote end steps for the Get Cookie command are:

  1. If the current browsing context is no longer open, return an error with code no such window.

  2. Let name be equal to "name" from match a request.

  3. Let result be an empty JSON list.

  4. Let cookies be a list of all cookies [[!RFC6265]] in the cookie store associated with active document address.

  5. Let length be the length of cookies.

  6. Let k be 0

  7. While k < length:

    1. Let cookie be the value in cookies at index k.

    2. If name is undefined:

      1. Append a serialised cookie to result.

    3. If name is defined and is equal to cookie-name:

      1. Append a serialised cookie to result.

    4. Increase the value of k by 1.

  8. Return success with data result.

A serialized cookie is created with the following algorithm:

  1. Let serialized cookie be an empty map.

    • Add an entry whose key is name and value is cookie-name as defined in [[!RFC6265]]

    • Add an entry whose key is value and value is cookie-value as defined in [[!RFC6265]]

    • If cookie's attribute-list contains an attribute with attribute-name of Path, let path be the attribute-value of the last attribute in the cookie-attribute-list with an attribute-name of "Path". Otherwise let path be null

      Add an entry to serialized cookie with key "path" and value path

    • If cookie's attribute-list contains an attribute with attribute-name of Domain, let domain be the attribute-value of the last attribute in the cookie-attribute-list with an attribute-name of "Domain". Otherwise let domain be null

      Add an entry to serialized cookie with key "domain" and value domain

    • If cookie's attribute-list contains an attribute with attribute-name of Secure, let secure be the attribute-value of the last attribute in the cookie-attribute-list with an attribute-name of "Secure". Otherwise let secure be null

      Add an entry to serialized cookie with key "secure" and value secure

    • If cookie's attribute-list contains an attribute with attribute-name of Expires, let expiry be the attribute-value of the last attribute in the cookie-attribute-list with an attribute-name of "Expires" specified in milliseconds since midnight, January 1, 1970 UTC using the format described in [[!RFC1123]]. Otherwise let expiry be null

  2. Return serialized cookie

addCookie()

HTTP Method Path Template Notes
POST /session/{sessionId}/cookie

A command named "addCookie" MUST follow:

  1. If the parameters object does not contain an element that can be coverted to Cookie return a unable to set cookie error.
  2. If the Document is a cookie-averse Document object then return an invalid cookie domain error.
  3. Set the Cookie in the user agent following the steps described in Storage Model in [[!RFC6265]]. If there is an error during this step return a unable to set cookie error.
Cookie cookie
A Cookie defining the cookie to be added. Store the Cookie in the user agent following the steps described in Storage Model in [[!RFC6265]].

Timeouts

This section describes how timeouts and implicit waits are handled within WebDriver

Setting Timeouts

The "timeouts" command is used to set the value of a timeout that a command can execute for.

setTimeouts()

HTTP Method Path Template Notes
POST /session/{sessionId}/timeouts

  • implicit - Set the amount of time the driver should wait when searching for elements. When searching for a single element, the driver should poll the page until an element is found or the timeout expires, whichever occurs first. When searching for multiple elements, the driver should poll the page until at least one element is found or the timeout expires, at which point it should return an empty list.
    If this command is never sent, the driver MUST default to an implicit wait of 0ms.
  • page load - Set the amount of time the driver should wait before returning when the page load stratgey is not "none". If this limit is exceeded, the get() command MUST return a "timeout" response status.
  • script - Set the amount of time the driver should wait after calling executeAsyncScript for the callback to have executed before returning a timeout Response.
The parameters will have the following keys in the object:
  • Let type contain the type of timeout for specified operations. Valid values are: "implicit", "page load", "script". If invalid values are passed in:
    • Set the HTTP Response status code to 500
    • Let status be equal to Invalid Selector
    • Let value to a stating that the strategy is invalid. It may return a list of valid search strategies.
  • let ms contain the amount of time, in milliseconds, that time-limited commands are permitted to run.

Interactions


The WebDriver API offers two ways of interacting with elements, either with a set of low-level "do as I say" actions, or a high-level "do as I mean" set of actions. The former are offered to allow precise emulation of user input. The latter are offered as a convenience to cover the common case, and can conceivably be implemented on top of the lower level primitive operations.
Interactions can be used to emulate single input actions as well as multiple, simultaneous actions.

Terms:


(NOTE: these are by no means the final terms, I needed them to make the prose easier to follow)

low-level action: The smallest operation an input source can do. These are used to build chains of actions. Example: keyDown
action chain: A chain of low-level actions
input source: The source from which the inputs will originate. MUST support 'keyboard', 'mouse' and 'touch'
source: The object currently acting on the source. For example, in a 'touch' environment, if two fingers are acting on a touchscreen, you will have two sources of input.

Interactable elements

User actions that operate on an element require the element to be interactable. The following conditions must be met for the element to be considered interactable:

Low-Level Actions


The low level actions provide a mechanism for precisely stating how a user can interact with the browser. This is achieved by sending a chain of low-level commands to a single endpoint. For example, if you wish to automate a drag and drop action in a browser, you would chain the pointerDown, pointerMove, pointerUp and release commands together.

The remote end will receive the action chain, execute them, and will return a response to the local end once the entire action sequence has been dispatched.

The set of actions available to you is depending on the input source. For example, on a keyboard you want to have a keyDown action to simulate pressing a specific key on the keyboard, but this is not a valid action on a touchscreen, where we care about pointer actions relative to coordinates or webelements.

Activation triggers generated by the WebDriver API User SHOULD be indistinguishable from those generated by a real user interacting with the browser. In particular, the dispatched events will have the isTrusted attribute set to true. The most robust way to dispatch these events is by creating them in the browser implementation itself. Sending OS-specific input messages to the browser's window has the disadvantage that the browser being automated may not be properly isolated from a user accidentally modifying input source state; use of an OS-level accessibility API has the disadvantage that the browser's window must be focused, and as a result, multiple tests cannot run in parallel.


Actions Endpoint

Sending an Action

HTTP Method Path Template Notes
POST /session/{sessionId}/actions

The 'actions' endpoint expects a list of objects as input. Each object in this list MUST contain the fellowing members:

Source

The "source" member will hold a string value to represent the input source. Implementations MUST support "keyboard", "mouse", and "touch" (TODO: use symbols?), and can be extended for any other input source.

id

This is a locally-assigned unique identifier. It will be used by the remote end to differentiate dispatched actions. For example, if you have a "touch" action with id "1" to represent one finger actively pressed on a screen, then you can dispatch another "touch" action with id "2" to represent a second finger on a screen, acting simultaneously.

actions

This holds a list of objects, where each object represents a low-level command. The list order dictates the order in which each command will be dispatched. Each command MUST have a 'name' member, whose value will hold the name of the command. More information on each command is in the action commands section.

So the structure will look as follows:
            [
              {
                "source": "string",
                "id": "string",
                "actions": [
                          { "name": "string: name of action primitive",
                            ... parameters to action commands...
                          },
                ]
              }
            ]
          

A list of dictionary objects are used so that we may use this same endpoint for parallel actions.
There is one endpoint for all input source's action chains.

Releasing all actions

HTTP Method Path Template Notes
DELETE /session/{sessionId}/actions


Use this command to clear all actions that are currently being performed. ALL actions currently being performed MUST be cancelled via pointerCancel if it is a "mouse" or "touch" source or via keyUp if it is a "keyboard" source.

NOTE: 'release' as a single command was removed since 'keyUp' and 'pointerUp'/'pointerCancel' exist and 'release' conflates them

Actions

This section describes the objects that are part of the "actions" member of the JSON structure sent to the "actions" endpoint.

General Actions

All input sources MUST implement the following action:

pause

The "pause" action MUST (TODO: or "may", since we can default to 0 on remote end?) take in a parameter named "duration" which will be the time to wait either in milliseconds or using a symbol. This action is used to indicate a period of time to wait between actions, and will also be used to indicate a period of inaction in parallel action chains.

If you wish to use a system specific wait period, please use the following symbols:
  • "CONTEXT" - wait for contextmenu
  • "CHAINED_EVENT" - wait period to join related events. For example, this should be used to join events for doubleclicking.

The remote end is responsible for translating these symbols to the platform specific periods.

Keyboard Actions

The following are actions that must be implemented for the "keyboard" input source. Their names will be used as the value to the "name" member of the data sent to the 'actions' endpoint. Each actions parameters are additional members to the object that "name" is a member of.

keyDown

The "keyDown" requires a parameter named "code" whose value will be one of the codes from the character types table. This action will send a "keyDown" event, with the specified key as a target.

keyUp

The "keyUp" requires a parameter named "code" whose value will be one of the codes from the character types table. This action will send a "keyUp" event, with the specified key as a target.

Pointer Actions

The following are actions that must be implemented for both "mouse" and "touch" input sources. Any future pointer-based source must implement these actions.
NOTE: conflating mouse and touch causes the pointerMove/pointerDown to events to be confusing and lacks verisimilitude: If you want to tap at element1, then that would mean 'put finger down on element1, remove finger from element1', for a tap, we have to decide if we want to send 'pointerMove, pointerDown, pointerUp' or 'pointerDown, pointerUp'. The latter matches the touch events sent (touchStart,touchEnd), and makes sense for touchscreens because there is no active button state (http://www.w3.org/TR/pointerevents/#glossary) until you dispatch a touchstart. sending a JSON structure with pointerMove, pointerDown, pointerUp for something that gets mapped to touchstart/touchend feels inelegant. We can enforce the following instead: if the "source" is mouse, then pointerMove,pointerDown,pointerUp is sent over the wire if the "source" is touch, then pointerDown,pointerUp is sent over the wire. if the "source" is anything else (stylus, or other), it will be defined later. The ramifications of this proposal would be that pointerDown must accept the parameters that pointerMove does (ie: ELEMENT, etc.).


pointerMove

The "pointerMove" action is used to move the pointer to a specific location on a page. In "mouse" sources, this would dispatch a "mouseMove" event. In "touch" sources, then if there is an active pointerDown action, this will generate a "touchmove" or "pointermove" event. For "touch" sources, pointerMove must not be called before pointerDown, since pointer sources only have move events once they are active on the screen.
When sending a "pointerMove", one of the following parameter sets MUST be used:
  • "ELEMENT" - "ELEMENT" will hold a WebElement's id, and this will dispatch the event to the center of that element, unless the following set of parameters is also included:
    • "x" - Integer, the x-coordinate relative to the top-left corner of the target WebElement. If this is not specifed, the midpoint of the width is used
    • "y" - Integer, the y-coordinate relative to the top-left corner of the target WebElement. If this is not specifed, the midpoint of the height is used
    • "x" and "y" - Integers, the coordinates relative to the top-left corner of the TODO: viewport, or top-left of root document?.


pointerDown

The "pointerDown" action is used to start an interaction on the page. In "mouse" sources, this would mean "mouseDown", in "touch" sources, this would mean "touchstart" or "pointerdown".

For "touch" sources, the following parameters must be passed:
  • "ELEMENT" - "ELEMENT" will hold a WebElement's id, and this will dispatch the event to the center of that element, unless the following optional set of parameters is also included:
    • "x" - Integer, the x-coordinate relative to the top-left corner of the target WebElement. If this is not specifed, the midpoint of the width is used
    • "y" - Integer, the y-coordinate relative to the top-left corner of the target WebElement. If this is not specifed, the midpoint of the height is used


For "mouse" sources, the following parameter must be passed:
  • "BUTTON" - "BUTTON" will hold a value describing which mouse button should be depressed.TODO: link to button chart


pointerUp

The "pointerUp" action is used to start an interaction on the page. In "mouse" sources, this would mean "mouseUp", in "touch" sources, this would mean dispatching an event like "touchend" or "pointerup".

Takes no parameters

pointerCancel

The "pointerMove" action is used to cancel an active pointer on the page. In "mouse" sources, this would mean "mouseUp", in "touch" sources, it implies cancelling the current action if possible by dispatching an event like "touchcancel" or "pointercancel".

Parallel Actions

Parallel actions are those that have more than one action acting simultaneously on the browser. An example of this is using multiple fingers to operate on a tablet screen at the same time.

Dispatching a parallel action also uses the actions endpoint. In order to send a parallel action, append multiple dictionaries to the list of dictionary objects. Each dictionary will hold all the actions from one input source. The list of actions each dictionary contains will be executed together in ticks, by stepping through each input source's action list in order and executing each step simultaneously.

The best way to understand this is through an example. Imagine we have two fingers acting on a touchscreen. One finger will press down on element1 at the same moment that another finger presses down on element2. Once these actions are done, the first finger will wait 5 seconds while the other finger moves to element3. Then both fingers release from the touchscreen.

To execute these actions, we must send the "actions" endpoint two dictionary objects in the JSON list of dictionaries, one fore each finger. We must use the "id" key of each object to uniquely identify each finger. The "actions" key will hold all the actions the input source will take.

The JSON for this set of actions is as follows:
              [
                {
                  "source": "touch",
                  "id": "1",
                  "actions": [
                            { "name": "pointerDown",
                              "ELEMENT": "element1"
                            },
                            { "name": "pause",
                              "duration": 0
                            },
                            { "name": "pointerUp"
                            }
                  ]
                },
                {
                  "source": "touch",
                  "id": "2",
                  "actions": [
                            { "name": "pointerDown",
                              "ELEMENT": "element2"
                            },
                            { "name": "pointerMove",
                              "ELEMENT": "element3"
                            },
                            { "name": "pointerUp"
                            }
                  ]
                }
              ]
            


When the remote end receives this, it will look at each input source's action lists. It will dispatch the first action of each source together, then the second actions together, and lastly, the final actions together.

The diagram below displays when each action gets executed. "Source 1" is the first finger, and "source 2" is the second.


There is no limit to the number of input sources, and there is no restriction regarding the length of each input's action list. Meaning, there is no requirement that all action lists have to be the same length. It is possible for one input source's action list may have more actions than another. As an example, imagine having two fingers on a touchscreen. The first finger will press on element1 while the second presses on element2, then the first will release the touchscreen while the second finger moves to element3, and finally the second finger releases from the touchscreen. In this case, the action list for the first finger contains 2 actions (pointerDown, pointerUp), and the action list for the second finger contains 3 (pointerDown, pointerMove, pointerUp). In this case, the JSON will look like this:
              [
                {
                  "source": "touch",
                  "id": "1",
                  "actions": [
                            { "name": "pointerDown",
                              "ELEMENT": "element1"
                            },
                            { "name": "pointerUp"
                            }
                  ]
                },
                {
                  "source": "touch",
                  "id": "2",
                  "actions": [
                            { "name": "pointerDown",
                              "ELEMENT": "element2"
                            },
                            { "name": "pointerMove",
                              "ELEMENT": "element3"
                            },
                            { "name": "pointerUp"
                            }
                  ]
                }
              ]
            
And the execution of each action will be done as follows:


Specific timing for the actions can also be expressed. The "pause" action can be used to either a) indicate a specific amount of time an input source must wait, or b) can be used to signify that the current input source must wait until all other actions in the tick are completed. For the former case, the current tick being executed must wait for the longest pause to complete. For example, in this diagram:



The remote end will dispatch the pointerDown actions in the first tick. In the second tick, since source 1 declares a pause of 5 seconds, the remote end will dispatch the pointerUp event for source 2, and will wait 5 seconds before moving on to executing the third tick.

In the event that one tick contains multiple pause durations, the remote end will wait the maximum duration before moving on to executing the next tick.

As noted before, "pause" can be used to signify inaction during a tick. If "pause" is declared without a time period, then the input source will not have any actions executed in the containing tick. As an example:



During tick 2, source 1 will have its pointerMove action dispatched, while source 2 will do nothing.

High Level Commands

These higher level commands SHOULD be built on top of the low level commands, and implement a user friendly way of interacting with a page in a way that models common user expectations.

Clicking

click()

HTTP Method Path Template Notes
POST /session/{sessionId}/element/{id}/click

Click in the middle of the WebElement instance. The middle of the element is defined as the middle of the box returned by calling getBoundingClientRect on the underlying document Element, according to the [[!CSSOM-VIEW]] spec. If the element is outside the viewport (according to the [[!CSS21]] spec), the implementation SHOULD bring the element into view first. The implementation MAY invoke scrollIntoView on the underlying document Element. The element MUST be displayed. See the note below for when the element is obscured by another element. Exceptions:

  • Links (A elements): Clicking happens in the middle of the first displayed bounding client rectangle. This is to overcome overflowing links where the middle of the bounding client rectangle does not actually fall on a clickable part of the link.
  • SELECT elements without the "multiple" attribute set. Clicking on the select element SHOULD open the drop down menu. The next click, on any element, MUST close this menu.
  • Clicking directly on an OPTION element (without clicking on the parent SELECT element previously) MUST open a selection menu, as if the SELECT option was clicked first, then click on the OPTION before finally closing the SELECT element's menu. The SELECT menu MUST be closed once the action is complete.

The possible errors for this command:

This command MUST use either the mouse or touch mechanisms for emulating the user input. In the case where the browser being automated supports only mouse input or both mouse and touch input, the low-level mouse mechanisms MUST be used. If the browser only supports touch input, the low level touch inputs MUST be used.

As the goal is to emulate users as closely as possible, the implementation SHOULD NOT allow clicking on elements that are obscured by other elements. If the implementation forbids clicking on obscured elements, an element not visible response MUST be returned and this SHOULD have an explantory message explaining the reason. The implementation SHOULD try to scroll the element into view, but in case it is fully obscured, it SHOULD NOT be clickable.

Touch

This section defines the low level commands used when manipulating touch-enabled devices. These are the building blocks of touch interaction chains.

Capability NameType
touchEnabledboolean


void tap ()

HTTP Method Path Template Notes
POST /session/{sessionId}/element/{id}/tap

Tap in the middle of the WebElement. The middle of the element is defined as the middle of the box returned by calling getBoundingClientRect on the underlying document Element, according to the [[!CSSOM-VIEW]] spec. If the element is outside the viewport (according to the [[!CSS21]] spec), the implementation SHOULD bring the element into view first. The implementation MAY invoke scrollIntoView on the underlying document Element. Exceptions:

  • Links (A elements): Clicking happens in the middle of the first displayed bounding client rectangle. This is to overcome overflowing links where the middle of the bounding client rectangle does not actually fall on a clickable part of the link.
  • SELECT elements without the "multiple" attribute set. Clicking on the select element SHOULD open the drop down menu. The next click, on any element, MUST close this menu.
  • Clicking directly on an OPTION element (without clicking on the parent SELECT element previously) MUST open a selection menu, as if the SELECT option was clicked first, then click on the OPTION before finally closing the SELECT element's menu. The SELECT menu MUST be closed once the action is complete.

The possible errors for this command:

Typing keys

A requirement for key-based interaction with an element is that it is interactable. Typing into an element is permitted if one of the following conditions is met:

  • The element is focusable as defined in the editing section of the [[!html51]] spec.
  • The element is allowed to be the activeElement. In addition to focusable elements, this allows typing to the BODY element.
  • In an HTML document, the element is editable as a result of having its contentEditable attribute set or the containing document is in designMode.
  • The underlying browser implementation would allow keyboard input to directed to the element (eg. an HTML document with a DIV marked as being contentEditable)

Prior to any keyboard interaction, an attempt to shift focus to the element MUST be attempted if the element does not currently have the focus. This is the case if one of the following holds:

  • The element is not already the document's activeElement.
  • The owner document of the element to be interacted with is not the focused document.

In case focusing is needed, the implementation MUST follow the focusing steps as described in the focus management section of the [[!html51]] spec. The focus MUST NOT leave the element at the end of the interaction, other than as a result of the interaction itself (i.e. when the tab key is sent).

clear()

Clear a TEXTAREA or text INPUT element's value.

HTTP Method Path Template Notes
POST /session/{sessionId}/element/{id}/clear

sendKeys()

HTTP Method Path Template Notes
POST /session/{sessionId}/element/{id}/value

Let value be an array of characters that will be typed into a WebElement

Sends a sequence of keyboard events representing the keys in the value parameter.

Caret positioning: If focusing was needed, after following the focusing steps, the caret MUST be positioned at the end of the text currently in the element. At the end of the interaction, the caret MUST be positioned at the end of the typed text sequence, unless the keys sent position it otherwise (e.g. using the LEFT key).

There are four different types of keys that are emulated:

  • Character literals - lower-case symbols.
  • Uppercase letters and symbols requiring the SHIFT key for typing.
  • Modifier keys
  • Special keys
The rest of this section details the values used to represent the different keys, as well as the expected behaviour for each key type.

When emulating user input, the implementation MUST generate the same sequence of events that would have been produced if a real user was sitting in front of the keyboard and typing the sequence of characters. In cases where there is more than one way to type this sequence, the implementation MUST choose one of the valid ways. For example, typing AB may be achieved by:

  • Holding down the Shift key
  • Pressing the letter 'a'
  • Pressing the letter 'b'
  • Releasing the Shift key
Alternatively, it can be achieved by:
  • Holding down the Shift key
  • Pressing the letter 'a'
  • Releasing the Shift key
  • Holding down the Shift key
  • Pressing the letter 'b'
  • Releasing the Shift key

Or by simply turning on the CAPS LOCK first.

The implementation MAY use the following algorithm to generate the events. If the implementation is using a different algorithm, it MUST adhere to the requirements listed below.

For each key, key in value, do

  1. If key is a lower-case symbol:
    1. If the Shift key is not pressed:
      1. Generate a sequence of keydown, keypress and keyup events with key as the character to emulate
    2. else (The Shift key is pressed)
      1. let uppercaseKey be the upper-case character matching key
      2. Generate a sequence of keydown, keypress and keyup events with uppercaseKey as the character to emulate
  2. Else if key is an upper-case symbol:
    1. If the Shift key is not pressed:
      1. Generate a keydown event of the Shift key.
      2. Generate a sequence of keydown, keypress and keyup events with key as the character to emulate
      3. Generate a keyup event of the Shift key.
    2. else (The Shift key is pressed)
      1. Generate a sequence of keydown, keypress and keyup events with key as the character to emulate
  3. Else if key represents a modifier key:
    1. let modifier be the modifier key represented by key
    2. If modifier is currently held down:
      1. Generate a keyup event of modifier
    3. Else:
      1. Generate a keydown event of modifier
    4. Maintain this key state and use it to modify the input until it is pressed again.
  4. Else if key represents the NULL key:
    1. Generate keyup events of all modifier keys currently held down.
    2. All modifier keys are now assumed to be released.
  5. Else if key represents a special key:
    1. Translate key to the special key it represents
    2. Generate a sequence of keydown, keypress and keyup events for the special key.

Once keyboard input is complete, an implicit NULL key is sent unless the final character is the NULL key.

Any implementation MUST comply with these requirements:

  • For uppercase letters and symbols that require the Shift key to be pressed, there are two options:
    • A single Shift keydown event is generated before the entire sequence of uppercase letters.
    • Before each such letter or symbol, a Shift keydown event is generated. After each letter or symbol, a Shift keyup event is generated.
  • A user-specified Shift press implies capitalization of all following characters.
  • If a user-specified Shift press precedes uppercase letters and symbols, a second Shift keydown event MUST NOT be generated. In that case, a Shift keyup event MUST NOT be generated implicitly by the implementation.
  • The NULL key releases all currently held down modifier keys.
  • The state of all modifier keys must be reset at the end of each sendKeys call and the appropriate keyup events generated

Character types

The value parameter contains a mix of printable characters and pressable keys that aren't text. Pressable keys that aren't text are stored in the Unicode PUA (Private Use Area) code points, 0xE000-0xF8FF. The following table describes the mapping between PUA and key:

Key Code Type
NULL\uE000NULL
CANCEL\uE001Special key
HELP\uE002Special key
BACK_SPACE\uE003Special key
TAB\uE004Special key
CLEAR\uE005Special key
RETURN\uE006Special key
ENTER\uE007Special key
SHIFT\uE008Modifier
CONTROL\uE009Modifier
ALT\uE00AModifier
PAUSE\uE00BSpecial key
ESCAPE\uE00CSpecial key
SPACE\uE00DSpecial key
PAGE_UP\uE00ESpecial key
PAGE_DOWN\uE00FSpecial key
END\uE010Special key
HOME\uE011Special key
ARROW_LEFT\uE012Special key
ARROW_UP\uE013Special key
ARROW_RIGHT\uE014Special key
ARROW_DOWN\uE015Special key
INSERT\uE016Special key
DELETE\uE017Special key
SEMICOLON\uE018Special key
EQUALS\uE019Special key
NUMPAD0\uE01ASpecial key
NUMPAD1\uE01BSpecial key
NUMPAD2\uE01CSpecial key
NUMPAD3\uE01DSpecial key
NUMPAD4\uE01ESpecial key
NUMPAD5\uE01FSpecial key
NUMPAD6\uE020Special key
NUMPAD7\uE021Special key
NUMPAD8\uE022Special key
NUMPAD9\uE023Special key
MULTIPLY\uE024Special key
ADD\uE025Special key
SEPARATOR\uE026Special key
SUBTRACT\uE027Special key
DECIMAL\uE028Special key
DIVIDE\uE029Special key
F1\uE031Special key
F2\uE032Special key
F3\uE033Special key
F4\uE034Special key
F5\uE035Special key
F6\uE036Special key
F7\uE037Special key
F8\uE038Special key
F9\uE039Special key
F10\uE03ASpecial key
F11\uE03BSpecial key
F12\uE03CSpecial key
META\uE03DSpecial key
COMMAND\uE03DSpecial key
ZENKAKU_HANKAKU\uE040Special key

The keys considered upper-case symbols are either defined by the current keyboard locale or are derived from the US 104 keys Microsoft Windows keyboard layout, which are:

  • A - Z
  • !$^*()+{}:?|~@#%_\" & < >

When the user input is emulated natively (see note below), the implementation SHOULD use the current keyboard locale to determine which symbols are upper case. In all other cases, the implementation MUST use the US 104 key Microsoft Windows keyboard layout to determine those symbols.

The state of the physical keyboard MUST NOT affect emulated user input.

Internationalized input

Non-latin symbols: TBD

Complex scripts using Input Method Editor (IME): TBD

Modals

This section describes how modal dialogs should be handled using the WebDriver API.

Conformance tests for this section can be found in the webdriver module under the "modals" folder.

window.alert, window.prompt and window.confirm

When the remote end is has a modal dialog such as those produced from window.alert, window.prompt and window.confirm it should allow the interrogation of the dialogues as using the following interface.

dismiss()

HTTP Method Path Template Notes
POST /session/{sessionId}/dismiss_alert

This will dismiss the modal. If the modal is an alert, this MUST be equivalent to calling accept() on the dialog. If no alert is present a no such alert error MUST be raised.

accept()

HTTP Method Path Template Notes
POST /session/{sessionId}/accept_alert

This will accept the modal. If the modal is from a window.prompt it is the equivalent of clicking the OK button. If no modal is present then a no such alert error MUST be raised.

getText()

HTTP Method Path Template Notes
GET /session/{sessionId}/alert_text

This will return the message shown in the modal. If no modal is present then a no such alert error MUST be raised.

sendKeys()

HTTP Method Path Template Notes
POST /session/{sessionId}/alert_text

This MUST act in the same manner as in sendKeys to an element. If the modal has no means for text input it should throw a Element not visible error. If no modal is present then a no such alert error MUST be raised.

Let value be an array of characters that will be typed into a WebElement. If the modal has no means of acceptiing text input it MUST raise a element not visible error

If a modal dialog is created from a onbeforeunload event the remote end MUST handle the dialog by either using accept or dismiss. These calls should either come from the local end or should be handled as an unexpected modal dialog as described below.

The remote end SHOULD have a mechanism to allow unexpected modal dialogs to be closed to prevent the remote end from becoming unusable. The default for this should be dismiss. The local end SHOULD allow a capability to be set that allows the default value to be overridden with accept. The local end SHOULD also allow setting the default behaviour to wait for a command to handle the modal. If the next command does not interact with the modal it MUST return a Unexpected alert open error to the local end.

Modal dialogs

If a browser supports Modal dialogs, as created by document.showModalDialog(), it MUST support handling of Modal dialogs via the WebDriver API. Modal dialogs can then be iterated over in the same approach as normal windows.

If close() is called on a parent window and it has modal dialogs open then the remote end SHOULD iterate over modal dialogs closing them before it closes the remaining windows so that it does not block the future commands to the remote end

Screenshots

Screenshots are a powerful mechanism for providing information to users of WebDriver, particularly once a particular WebDriver instance has been disposed of. In different circumstances, users want different types of screenshot. Note that the WebDriver spec does not provide a mechanism for taking a screenshot of the entire screen.

In all cases, screenshots MUST be returned as lossless PNG images encoded using Base64. Local ends MUST provide the user with access to the PNG images without requiring the user to decode the Base64. This access MUST be via at least one of a binary blob or a file.

All commands within this section are implemented using the "TakesScreenshot" interface:

takeScreenshot()

HTTP Method Path Template Notes
GET /session/{sessionId}/screenshot

Take a screenshot and return a lossless PNG encoded using Base64. If element is not populated or is null then the User Agent MUST return the screenshot of the current state of the document at the top level browsing context.

The possible errors for this command:

Leaving below until Bug 27920 has a consensus

optional WebElement? element
The WebElement on which to operate. If element is not populated or is null then the User Agent MUST return the screenshot of the current state of the document at the top level browsing context.

Current Top Level Browsing Context

Capability NameType
takesScreenshotboolean

If this capability is supported, local end MUST add the TakesScreenshot interface to the WebDriver interface.

This command will take a screenshot of the return the screenshot of the current state of the document at the top level browsing context. Implementations of the remote end SHOULD capture the entire document, even if this would require a user to scroll the browser window. That is, the returned PNG SHOULD have the same width and height as returned by a call to getSize of the BODY element and MUST contain all visible content on the page, and this SHOULD be done without resizing the browser window. If the remote end is unable to capture the entire Document, then the part of the Document currently displayed in UI of the browser MUST be captured without additional chrome such as scrollbars and browser chrome.

One way to think of capturing the entire Document is that the user has an infinitely large monitor and has resized the window to allow all content to be visible. One of those monitors would be very cool.

Nested frames MUST be sized as if the user has resized the window to the dimensions of the PNG being returned. This often means that not all potentially visible content within the nested frames is captured.

Remote ends MUST NOT attempt to track changes in window size as the screenshot is being taken. In particular this means that in the case of a page that makes use of "infinite scrolling" (where an AJAX call is used to populate additional content as the user scrolls down) or in some other way resizes content as the window size is changed only the content that was originally contained in the Document when the command is executed will be captured.

Element

Capability NameType
takesElementScreenshotboolean

If this capability is supported, local end MUST add the TakesScreenshot interface to the WebElement interface.

HTTP Method Path Template Notes
GET /session/{sessionId}/screenshot/{ELEMENT}

Handling non-HTML Content

Non-HTML content MUST be treated in the same manner as HTML if the Non-HTML if the browser creates a Document object for the content of the document. If a Document Object is not created then how it handled SHOULD be non-normative

XML

This section describes XML documents as described in [[XML10]]. For XHTML documents the remote end should treat them as HTML documents and not have the caveats, below, applied.

Since Browsers create a Document object for XML pages it is expected that we can interogate them as a normal HTML document however the following differences should be noted:

SVG

This section described SVG documents in a browser as described by [[SVG2]]. Since browsers create a Document tree for SVG documents it is expected that WebDriver can interrogate the Document as a normal HTML document.

Working with Accessibility APIs

Many accessibility APIs represent the UI as a series of nested nodes. It is possible to map these nodes to WebElement instances. In order to function properly, it is likely that additional element locating strategies will be required.

This is one way in which it might be possible to test mobile applications that marry a native wrapper around a series of HTML views.

Extending the Protocol

Vendor-specific Extensions

The WebDriver protocol is designed to allow extension to meet vendor-specific needs, such as interacting with the chrome of a browser. Vendor-specific extensions are implemented by appending a prefix to the command name. This should be of the form:

        '-' + vendor prefix + '-' + command name
      

For example: "-o-open-bookmark" or "-moz-install-extension".

It is guaranteed that no command name in this or future versions of the WebDriver specification will be prefixed with a leading dash.

It is suggested that vendors use the same vendor identifier as in [[!CSS21]] (notably, section 4.1.2.2)

Extending the JSON/HTTP Protocol

This section is non-normative.

The wire protocol (see Appendix below) makes use of URLs to distinguish command names. When extending the protocol by adding new URLs, vendors should use their vendor prefix without additional characters to prevent any potential clashes with other implementations. This leads to URLs of the form: http://host:port/session/somekey/moz/extension.

Capabilities

This section is non-normative.

Capabilities are used by WebDriver implementations to enumerate the parts of this specification that they support. They are also used when establishing a new session to descrive the required or desired capabilities. This appendix collects the capabilities mentioned in this spec into one place.

Command Format

This is essentially the content at the start of the json wire protocol

Thread Safety

There is no requirement for local or remote implementations to be thread safe. Local ends SHOULD support serialized access from multiple threads.

Security and Privacy

The following section is non-normative.

Privacy

The local end SHOULD create a new profile when creating a new session. If a new profile can be created it MUST NOT copy the profile in use and MUST create a fresh profile. By creating a new profile the user agent will prevent any unexpected behaviour when the remote end is accessing content.

Security

The remote end SHOULD have a specific command line argument when starting the browser up if it is connecting to a browser (e.g. firefox.exe --webdriver ) and SHOULD have user agent configuration preference that is tested when the user agent starts up

When the remote end starts up, it MUST include a flag or setting to limit the IP addesses allowed to connect and create sessions. The default value for this setting SHOULD limit connections to be from 127.0.0.1 IPV4 address or ::1 IPV6 address. This will prevent arbitrary machines from connecting and creating WebDriver sessions unless specifically configured to allow them, while still supporting use-cases where the local end runs on a different machine from the remote end.

Some devices will require the device to be placed into a 'developer' mode. This allows unix sockets to be forwarded on to the device while the device is connected to a host. An example of this is if the local end needed to go through a remote debugger protocol.

If any of these fail then a session not created error MUST be thrown when the local end tries to create a new session.

Fingerprinting

The following will allow web sites to know that the user interacting with the content is not a real user. This can be used to prevent denial of service attacks.

When the user agent creates a new session it MUST add a read only property to window.navigator.webdriver. The value should be set to true when WebDriver has an active session. When WebDriver does not have an active session then the value is equal to false or the property is removed.

Acknowledgements

Many thanks to Robin Berjon for making our lives so much easier with his cool tool. Thanks to Jason Leyba, Malcolm Rowe, Ross Patterson and Andrey Botalov for proof reading and suggesting areas for improvement. Thanks to Jason Leyba, Eran Messeri, Daniel Wagner-Hall, Malini Das, Luke Inman-Semerau, Andreas Tolfsen and James Graham for contributing sections to this document. Also thanks to the following people for their contribution of patches and test cases:

These links are only here until we have fixed ReSpec.js to avoid creating anchors to things that don't exist.