Web Automation Markup Language.
Give WAML a try with the online WAML editor.
Here you will find the full WAML Specification, examples of what it looks like, and general information regarding the project.
The Web Automation Markup Language (WAML) defines a standard, programming language-agnostic specification for a sequence of steps which can be performed on web pages within the context of a web browser.
The WAML schema is based on JSON Schema draft-07 defined here.
waml: 0.1.0
steps:
- visit: https://google.com
- fill:
selector: input#search
value: Ugandan knuckles
- click: a#search
- wait: 10
- snap:
filename: test
format: pngWAML documents are represented in either YAML or JSON formats. These documents may be written manually or generated dynamically from an application (such as a browser extension.) WAML is both human and machine-readable.
The WAML specification can be used to define flows for:
- Web scraping / data extraction
- Content monitoring (Online review monitoring, competitor monitoring, price drops, new releases)
- Content aggregation (Business profile data, leads, jobs, news, events)
- Turning websites into APIs
- Web automation
- Integration end-to-end testing
- Uptime monitoring
- Evaluating web best practices (SEO, HTML best practices)
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
A WAML document represents a single Scenario, a sequence of Steps in a specified browser Context. Each Step corresponds to a single user action such as clicking a button, typing into a form, and so on.
A WAML document consists of many Fields.
Here is an example WAML document which exercises all possible fields and options.
waml: 0.1.0
info:
title: An example WAML document.
description: High-level summary of the scenario.
variables:
someValue: Hello world
isMobile: true
context:
viewport:
width: 800
height: 600
headers:
X-API-Key: 123
Authorization: Bearer abc
cookies:
- cookieName: cookieValue
mediaType: screen
userAgent: myUserAgent
device: iPhone4
timeout: 5
steps:
- visit: https://google.com
- click: a.link
- hover: a#about
- focus: input#search
- select:
selector: select#colors
value: 'blue'
- fill:
selector: input#search
value: Ugandan knuckles
- type: ${someValue}
- press: Shift
- scroll: 100
- scroll: a#load-more
- scroll:
- wait: div#results
- wait: 3000
- wait:
- refresh:
- back:
- forward:
- scrape:
articles:
- select article {0,}
- body: select .body | get html
imageUrl: select img | get attr src
summary: select .body p:first-child | get text
title: select .title | get text
checked: select input[type="checkbox"] | get prop checked
- setContext:
viewport:
height: 400
width: 300
- snap:
filename: test
format: png
- pdf: testThe table below lists the 5 root-level fields of a WAML document.
| Field Name | Type | Description |
|---|---|---|
| waml | string |
REQUIRED. The string must be the semantic version number of the WAML Specification that the WAML document uses. |
| info | InfoObject |
Provides metadata about the scenario. |
| variables | object |
Stores variables used in the steps field. |
| context | ContextObject |
Defines the browser's context and emulation configuration. |
| steps | []StepObject |
REQUIRED. A sequence of steps for the scenario. |
All field names in the specification are case sensitive.
The WAML Specification is versioned using Semantic Versioning 2.0.0 (semver) and follows the semver specification.
A WAML document must begin with a version declaration within the top-level waml field. The waml field must contain the document's WAML Specification's semantic version number.
The waml field is required.
waml: 0.1.0The Info field provides general information about the Scenario.
The info field is optional.
info: # Metadata about the WAML document
title: An example WAML document.
description: High-level summary of the user scenario.| Field Name | Type | Description |
|---|---|---|
| title | string |
The title of the scenario. |
| description | string |
A short summary of the scenario. |
The Variables field stores variables usable elsewhere in the Scenario, such as in the steps field.
You can store any key-value pairs. Values must be a literal value (string, number, or boolean).
The use of variables and the variables field is optional.
variables: # A mapping of variables to be defined in the scenario context
searchTerm: Hello world
isMobile: trueYou can reference any pre-defined variables with the
${variable}syntax.
steps:
- fill:
selector: input#search
value: ${searchTerm}Referencing a variable in
stepsthat is not defined beforehand in thevariablesfield SHOULD cause a WAML implementation to raise a validation error.
The Context field defines the browser's context and emulation configuration.
The context field is optional.
context: # Browser emulation settings (optional)
viewport: # Browser window dimensions
width: 800
height: 600
headers: # Additional HTTP headers to be sent with every request
X-API-Key: 123
Authorization: Bearer abc
cookies: # Browser cookies
- cookieName: cookieValue
mediaType: screen # screen / print / none
userAgent: myUserAgent # Browser user agent
timeout: 5 # Maximum navigation time
device: 'iPhone4'| Field Name | Type | Description |
|---|---|---|
| viewport | ViewportObject |
The width and height of the viewport. |
| headers | object |
A set of key-value pairs containing additional HTTP headers to be sent with every request. |
| cookies | []CookieObject |
A set of key-value pairs containing cookies of the browser context. |
| mediaType | string |
The browser's media type. Values can be "screen" or "print". |
| userAgent | string |
The browser's user agent string. |
| timeout | integer |
The maximum navigation timeout in milliseconds. |
| device | string |
Device descriptor to emulate. List here. |
The Steps field contains a sequence of one or more steps. Each step is a StepObject that represents a particular user action, such as clicking an HTML element.
The steps field is required.
steps: # A sequence of user interactions
- visit: https://google.com # Navigating to a URL
- fill: # Focus to an element and type things in
selector: input#search
value: Ugandan knuckles
- click: a#search # Click an HTML element
- wait # Wait for a page load to finish
- snap: # Take screenshot of the page
filename: foo
format: pngSteps can have a compact version which omits default and optional parameters, and an expanded version with additional parameters & features. For example, the click step normally just needs a CSS selector:
Compact version
- click: a.link # Click an HTML elementBut you can also use the expanded version of click to specify a target from a list of elements:
Expanded version
- click: # Expanded version of click
selector: a.link
index: 2 # click 3rd element from a listThe variable store is an ephemeral, mutable key-value store for reading and storing values to be used elsewhere in the Scenario. At the start of a Scenario, the variable store can be initialized through the variables field:
variables:
someValue: Hello world
isMobile: trueVariables can be read using the
${}syntax:
steps:
- fill:
selector: input#search
value: ${someValue}Steps such as
scrapesaves its results into the variable store.
- scrape:
articles:
- select article {0,}
- body: select .body | get html
imageUrl: select img | get attr src
summary: select .body p:first-child | get text
title: select .title | get text
checked: select input[type="checkbox"] | get prop checkedAt the end of a WAML Scenario, the contents of the variable store should be returned and the variable store cleared.
The table below lists the step types available in WAML:
| Step Name | Description |
|---|---|
| visit | Navigate to a specified URL. |
| click | Click an element. |
| hover | Hover over an element. |
| focus | Focus to an element. |
| select | Focus and select one or more values from a dropdown element. |
| fill | Focus an type a string into an input element. |
| type | Type a string of characters. |
| press | Type a special key, such as Shift and Enter. |
| wait | Wait for a specified interval, for an element to load, or for a page load to finish. |
| refresh | Refresh the current page. |
| back | Move backward in the browser history. |
| forward | Move forward in the browser history. |
| scrape | Scrape the HTML document for specified elements and attributes. |
| assert | Evaluates a runtime assertion. Aborts the scenario if false. |
| setContext | Modify browser context / emulation settings. |
| snap | Take a screenshot of the page. |
Boldedproperties are required properties.
The visit step navigates to a specified URL.
- visit: https://google.com| Property | Description | Type | Default |
|---|---|---|---|
url |
The URL to navigate. Must be prefixed with either http:// or https://. |
string |
undefined |
The click step clicks a specified HTML element by CSS selector.
If there are multiple elements satisfying the selector, the first will be clicked.
- click: a.link # Clicks first matching element- click:
selector: ytd-thumbnail.ytd-video-renderer
index: 2 # Clicks 3rd video from a list of elements| Property | Description | Type | Default |
|---|---|---|---|
selector |
The CSS selector of an HTML element. | string |
undefined |
index |
Index of element, if there are multiple matching elements. | integer |
undefined |
The hover step hovers the mouse pointer over a specified HTML element.
If there are multiple elements satisfying the selector, the first will be hovered.
- hover: a#sign-in| Property | Description | Type | Default |
|---|---|---|---|
selector |
The CSS selector of an HTML element. | string |
undefined |
The focus step focuses over a specified HTML element.
If there are multiple elements satisfying the selector, the first will be focused.
- focus: input#search| Property | Description | Type | Default |
|---|---|---|---|
selector |
The CSS selector of an HTML element. | string |
undefined |
The select step focuses over a specified dropdown element and selects one or more values.
If the <select> HTML element has the multiple attribute, all values are considered, otherwise only the first one is taken into account.
- select:
selector: select#colors
value: 'blue'- select: # Focusing and selecting one or more values from a dropdown
selector: select#colors
value:
- 'blue'
- 'red'
- 'green'| Property | Description | Type | Default |
|---|---|---|---|
selector |
The CSS selector of an HTML element. | string |
undefined |
value |
One or more values. | array |
undefined |
The fill step types a string of text into a focused HTML element, usually form inputs.
- fill:
selector: input#search
value: Ugandan knuckles| Property | Description | Type | Default |
|---|---|---|---|
selector |
The CSS selector of an HTML element. | string |
undefined |
value |
String of text to type in. | string |
undefined |
The types step types a string of text.
- type: Hello world 123 嗨| Property | Description | Type | Default |
|---|---|---|---|
value |
String of text to type in. | string |
undefined |
The press step types special keys such as Shift and Enter.
- press: ArrowLeft| Property | Description | Type | Default |
|---|---|---|---|
key |
Name of key to press, such as ArrowLeft. See USKeyboardLayout for a list of all key names. |
string |
undefined |
The scroll step scrolls the browser's viewport by a specified number of pixels, a specified HTML element, or to the bottom of the page (for infinite scrolls.)
- scroll: 100 # Scroll 100 pixels
- scroll: a#load-more # Scroll to HTML element
- scroll: # Infinite scroll| Property | Description | Type | Default |
|---|---|---|---|
value |
Integer, CSS selector, or 'infinite'-ly. | string or integer |
undefined |
The wait step lets you wait by a specified interval, for an HMTL element to load, or for a page navigation to finish.
- wait: div#results # Selector of an element to wait for
- wait: 3000 # Time to wait
- wait: # Wait for a page load to finish| Property | Description | Type | Default |
|---|---|---|---|
selector |
The CSS selector of an HTML element. | string |
undefined |
timeout |
Number of milliseconds to wait for. | integer |
0 |
The refresh step refreshes the current page.
- refresh:The back step moves the current page backward in browser navigation history.
- back:The forward step moves the current page forward in browser navigation history.
- forward:The scrape step lets extract and evaluate attributes and HTML elements of the current page.
| Property | Description | Type | Default |
|---|---|---|---|
DOM extraction expression |
An object containing a declarative DOM extraction expression. | object |
undefined |
The
scrapestep accepts as input a declarative DOM extraction expression based onsurgeon.
You describe the content you wish to scrape using select and get keywords.
select '.post-title a' {0,}
Property | Description | Type | Default | Example
---------|:-----------:|:----:|-------------- :|--------------
CSS selector | A CSS selector. | string | undefined | div.my-class a
quantifier | Slicing & indexing quantifier to pick amongst matches. | string | [0] | {0,4}[2]
The select keyword accepts as input a CSS selector (e.g. .body p:first-child).
By default, the first matching element is selected. To select multiple or the N-th element, supply a third argument. This 'quantifier' argument is used to select single or multiple CSS selector matches, and to pick specific indexes from the list. For example, select div {0:2}[1] selects the first two matches ({0:2}), and picks the second ([1]) - returning a single element. Read this for more details on the quantifier expression.
get attr src
get prop innerHTML
get html
get text
Property | Description | Type | Default | Example
---------|:-----------:|:----:|-------------- :|--------------
content type | Content to extract. | string | undefined | text, html, prop, attr
content name | Name of property or attribute to extract. | string | undefined | src
The get keyword accepts as input one of text, html, prop, and attr for extracting text, raw HTML content, DOM properties, and HTML attributes respectively.
The get keyword accepts a name argument in the case of prop and attr, which specifies the name of the property (e.g. checked) or attribute (e.g. src) to get.
Below is an example of both
selectandgetkeywords used together.
- scrape:
articles:
- select article {0,}
- body: select .body | get html
imageUrl: select img | get attr src
summary: select .body p:first-child | get text
title: select .title | get text
checked: select input[type="checkbox"] | get prop checkedThe above WAML will produce the following structured data:
{
articles: [
{
body: ...
imageUrl: ...
summary: ...
title: ...
},
{
body: ...
imageUrl: ...
summary: ...
title: ...
}
],
checked: ...
}Subroutines can be nested: HTML elements from a previous level is passed as arguments to the next level. Take a look at the following example:
- select article
- body: select .body | get html
imageUrl: select img | get attr src
summary: select .body p:first-child | get text
title: select .title | get textLet's walk through these steps:
- The
selectline returns a list of one or more HTML elements with the selectorarticle. This is equivalent todocument.querySelectAll('article'). - In the next line, we name and extract
body,imageUrl,summary, andtitlewith theselection in the first line as input.
In this example,
bodyis equivalent to:
document.querySelector('article').querySelector('.body').innerHTML
imageUrlis equivalent to:
document.querySelector('article').querySelector('img').getAttribute('src')You can use the | pipe operator to simplify a list of expressions:
# Before
- body:
- select .body
- get htmlThe two examples here are equivalent.
Into the following one-liner:
# After
- body: select .body | get htmlThe Assert Step allows you to perform runtime assertions with Javascript expressions. The results of the assertions are saved into the variable store.
| Property | Description | Type | Default |
|---|---|---|---|
expression |
Javascript expression. | string |
undefined |
message |
Description of the assertion. | string |
undefined |
- assert:
expression: "'${pageTitle}' === 'My Page Title'"
message: Valid page titleThe SetContext step updates the browser context / emulation settings.
| Property | Description | Type | Default |
|---|---|---|---|
context |
Context object containing headers, cookies, etc. | Context Object |
undefined |
- setContext:
viewport:
width: 800
height: 600
headers:
X-API-Key: 123
Authorization: Bearer abc
cookies:
- cookieName: cookieValue
mediaType: screen
userAgent: myUserAgent
device: 'iPhone4'
timeout: 5The snap step takes a screenshot of the current page and saves it into the local filesystem or a cloud storage.
| Property | Description | Type | Default |
|---|---|---|---|
filename |
The filename to save the image as. | string |
undefined |
format |
The format to save the image as. PNG and JPG formats supported. | string |
png |
fullPage |
If set to true, takes a screenshot of the full scrollable page. | boolean |
false |
- snap: # Take screenshot of the page
filename: my-image
format: png
fullPage: trueThe pdf step saves the current page as a PDF into the local filesystem, relative to current working directory.
| Property | Description | Type | Default |
|---|---|---|---|
filename |
The filename to save the PDF as. | string |
undefined |
- pdf: my-pdfWAML provides the following flow control abstractions:
The if and unless optional attributes can be specified in a Step to perform conditional execution.
Pass in a Javascript expression that returns a
boolean.
- click:
selector: a#search
if: ${someValue} === "submit"The
clickStep above will be executed onlyifthe expression${someValue} === "submit"evaluates totrue.
You can reference variables from the Variable Store within your Expression.
| Property | Description | Type | Default |
|---|---|---|---|
if |
If set, the step is only executed if the value evaluates to true. |
Expression |
undefined |
unless |
If set, the step is only executed if the value evaluates to false. |
Expression |
undefined |
WAML is an evolving spec. Documentation, bug reports, pull requests, and all other contributions are welcome!
waml © 2018+, Yos Riady. Released under the MIT License.
Authored and maintained by Yos Riady with help from contributors (list).