Browsing

Visit pages, find elements with smart selectors, act on them.

On this page

Browsing

Open pages, find elements and act on them. Every action waits for its element, and every action returns the page, so calls chain.

playwright( { baseURL : "http://localhost:8080" } ).browse( ( page ) => {
	page.visit( "/login" )
		.fill( "Email", "luis@ortus.com" )     // by label, placeholder or name
		.fill( "Password", "secret" )
		.check( "Remember me" )
		.select( "@role", "editor" )           // @testId
		.click( "Sign in" )                    // by button or link text
		.assertPathIs( "/dashboard" )
} )

Smart selectors

One string finds elements:

SelectorFinds
Visible textfill() looks for a label, placeholder or name; click() for a button or link
@namedata-testid="name" (see the testIdAttribute setting), or a page object alias
#id, .class, input[name=email], ul li, h1CSS (lowercase tag names)
//div, xpath=..., css=..., text=..., role=button[name="Save"]Playwright selectors
ref=e12An element ref from an AI snapshot

Explicit finders return a locator: locator(), byRole( "button", { name : "Save" } ), byText(), byLabel(), byPlaceholder(), byTestId(), byAltText(), byTitle(), frame( "iframe.preview" ).

Id selectors in BoxLang strings

# starts interpolation in a BoxLang string, so write an id selector as "##email", or use "input[name=email]" or a test id.

Actions

MethodDoes
visit( url, options )Navigate (relative to baseURL), or visit a page object
click( sel ), dblclick( sel ), hover( sel ), focus( sel )Mouse and focus
fill( sel, value ), type( sel, text ), clear( sel )Inputs
press( key ), press( sel, key )Keys: Enter, Tab, Control+A, ControlOrMeta+S
check( sel ), uncheck( sel ), select( sel, values ), upload( sel, files )Forms
drag( from, to ), scrollTo( sel )Other
back(), forward(), reload(), setContent( html )Navigation
within( sel, callback )Scope actions to an element

On a locator, actions without a selector act on the locator: page.byLabel( "Email" ).fill( "a@b.com" ), page.byLabel( "Resume" ).upload( "cv.pdf" ).

Locators

todos = page.locator( ".todos li" )
todos.count()                                  // 3
todos.texts()                                  // [ "Write specs", ... ] (visible elements only)
todos.first().text()
todos.nth( 2 ).text()                          // 1-based: nth( 0 ) throws
todos.filter( { hasText : "Ship" } ).click()
todos.filter( { has : page.locator( ".done" ) } ).count()
todos.all().each( ( todo ) => println( todo.text() ) )

Also last(), visible(), isChecked() and isEnabled(). filter() takes hasText, hasNotText, has, hasNot and visible.

Reading

url(), title(), content(), text( sel ), html( sel ), value( sel ), attribute( sel, name ), count( sel ) (every match), isVisible( sel ) (true when any match is visible), evaluate( js, arg ), snapshot().

Waiting

Actions and assertions already wait, so you rarely need these:

waitFor( sel, state ), waitForText( text ), waitForUrl( url ), waitForLoadState( state ), wait( ms ).

Popups and downloads

popup    = page.waitForPopup( () => page.click( "Open preview" ) )
download = page.waitForDownload( () => page.click( "Export CSV" ), "exports/orders.csv" )
println( download.path )     // also suggestedFilename and url

Dialogs (alert, confirm, prompt) are dismissed unless you listen with onDialog(), see Network and APIs.

Viewport, media and time

page.setViewport( 375, 812 )
page.emulate( { media : "print", colorScheme : "dark" } )
page.freezeTime( "2026-01-01T09:00:00" )     // Date.now() is fixed, timers keep running

page.clock() returns Playwright's clock for full control of timers. To start a page with a device, locale or color scheme, use a profile or settings.

Discover the API

Every object describes itself from its docblocks: page.help(), page.help( "fill" ), playwright().help().

Edit this page Download Markdown Last updated Oct 23, 2026, 3:55:59 PM Report an issue