Taiko Getting Started: Browser Automation with Node.js
Taiko is an open-source browser automation library built by ThoughtWorks. It uses a Node.js API and Chrome DevTools Protocol (CDP) directly — no WebDriver intermediary. The result is a faster, more reliable automation tool with a selector model designed to match how users actually interact with pages.
What Makes Taiko Different
Taiko's key design choices:
- Smart selectors: Finds elements by proximity to labels, not just CSS paths
- Implicit wait: Waits for page load and network activity automatically — no manual waits for most actions
- REPL mode: Interactive session for exploring and debugging selectors
- CDP-native: Direct Chrome DevTools Protocol, not WebDriver — faster and more reliable
Taiko is frequently used with Gauge, ThoughtWorks' test framework, but it works standalone with any test runner.
Installation
npm install --save-dev taikoThis installs Taiko and downloads Chromium automatically. No separate browser driver installation needed.
Verify the installation:
npx taiko --versionFirst Script
Create tests/first-test.js:
const { openBrowser, goto, click, type, closeBrowser, $, text } = require('taiko');
(async () => {
try {
await openBrowser({ headless: true });
await goto('https://example.com');
console.log('Page loaded');
await closeBrowser();
} catch (e) {
console.error('Test failed:', e);
await closeBrowser();
process.exit(1);
}
})();Run it:
node tests/first-test.jsCore Actions
Taiko provides a flat API of action functions:
const { openBrowser, goto, click, type, write, press, closeBrowser,
$, text, button, link, inputField, checkBox, dropDown,
waitFor, screenshot, focus } = require('taiko');
// Navigation
await goto('https://example.com/login');
await reload();
// Typing
await write('user@example.com', into(inputField('Email')));
await type('password123', { into: $('input[name=password]') });
// Clicking
await click('Sign In'); // find by text
await click(button('Submit')); // find button by text
await click(link('Forgot password?')); // find link by text
await click($('#submit-btn')); // find by CSS selector
// Form interactions
await checkBox('Remember me').check();
await dropDown('Country').select('United States');
// Keyboard
await press('Enter');
await press('Tab');
// Waiting
await waitFor(2000); // fixed wait (avoid when possible)
await waitFor(() => text('Success').exists()); // conditional wait
// Utilities
await screenshot({ path: 'output.png' });
await scrollDown();
await scrollUp();Smart Selectors
This is Taiko's most distinctive feature. Rather than requiring CSS paths, Taiko finds elements based on how they relate to visible text on the page.
Text-Based Selectors
// Find elements by their visible text
await click('Sign In');
await click(button('Add to Cart'));
await click(link('Privacy Policy'));Proximity Selectors
Find inputs by their associated label text, even without for/id attributes:
// Find input near the label "Email Address"
await write('user@example.com', into(inputField('Email Address')));
// Find input to the right of the label "Username"
await write('alice', into(inputField(toRightOf('Username'))));
// Find checkbox below a heading
await checkBox(below('Notifications')).check();Proximity selectors are powerful for forms where CSS selectors are fragile or where id/name attributes aren't set.
CSS Selectors
Standard CSS selectors with $():
await click($('button.primary'));
await type('search term', { into: $('input[type=search]') });Combining Selectors
// Button with specific text inside a specific container
await click(button('Delete', within($('#actions-panel'))));
// Link near specific text
await click(link(near('Alice Johnson')));Writing Tests with a Test Runner
Taiko works with any Node.js test runner. Here's a Mocha example:
const { openBrowser, closeBrowser, goto, write, click,
button, text, inputField, $, waitFor } = require('taiko');
const assert = require('assert');
describe('Login flow', () => {
before(async () => {
await openBrowser({ headless: true });
});
after(async () => {
await closeBrowser();
});
it('allows valid login', async () => {
await goto('https://example.com/login');
await write('alice@example.com', into(inputField('Email')));
await write('password123', into(inputField('Password')));
await click(button('Sign In'));
assert.ok(await text('Welcome, Alice').exists());
});
it('shows error for wrong password', async () => {
await goto('https://example.com/login');
await write('alice@example.com', into(inputField('Email')));
await write('wrongpassword', into(inputField('Password')));
await click(button('Sign In'));
assert.ok(await text('Invalid credentials').exists());
});
});Interactive REPL
Taiko's REPL is useful for exploring a page and building selectors interactively:
npx taikoIn the REPL:
> openBrowser()
> goto('https://example.com')
> $('h1').text()
'Example Domain'
> click('More information...')
> screenshot()Once you've found the right selectors, copy the commands into your test file. The REPL dramatically speeds up test development.
Headless Configuration
// Headless (for CI)
await openBrowser({
headless: true,
args: [
'--no-sandbox',
'--disable-dev-shm-usage'
]
});
// With visible browser (for debugging)
await openBrowser({ headless: false });
// Slow motion (for debugging timing issues)
await openBrowser({
headless: false,
slowMo: 100 // 100ms between actions
});Running in CI
TAIKO_BROWSER_ARGS="--no-sandbox,--disable-dev-shm-usage" npx mocha tests/Or set in code:
await openBrowser({
headless: true,
args: process.env.CI
? ['--no-sandbox', '--disable-dev-shm-usage']
: []
});Implicit Waiting
Taiko automatically waits for:
- Page load to complete after navigation
- Network requests to settle after actions
- Elements to be interactive before acting on them
This means you don't need waitFor after most clicks and form submissions. Add explicit waitFor only when you need to wait for a specific condition:
// Usually not needed — Taiko waits for page load automatically:
await goto('https://example.com/dashboard');
// Dashboard is already loaded here
// Needed for AJAX content that loads after the page:
await waitFor(() => text('Results').exists());Summary
Taiko's value proposition is a cleaner automation experience: smart selectors that survive UI refactors, implicit waiting that removes timing boilerplate, and a REPL for interactive exploration. It runs on Node.js, uses Chrome directly via CDP, and integrates with any test framework.
The smart selectors are the standout feature — inputField('Email Address') is more resilient than $('form > div:nth-child(2) > input') and communicates intent clearly. That alone makes Taiko worth evaluating for Node.js teams.