Karate's UI module lets you drive a browser from the same .feature file as your API tests. No Selenium, no WebDriver server to start manually, no separate test framework. The same Given/When/Then syntax that sends HTTP requests can also click buttons, fill in forms, and assert on page content. This lesson is an introduction to Karate UI's capabilities and, equally important, to when you should use it and when you should reach for a dedicated UI tool instead.
The driver keyword — opening a browser
To start a browser and navigate to a URL:
Given driver 'https://myapp.com/login'Karate launches a Chrome instance using the WebDriver protocol (or Chrome DevTools Protocol, depending on configuration). The driver keyword replaces a url + method get pair — it's the entry point for browser sessions.
By default Karate uses Chrome in headed mode locally. For CI, add a driver configuration in karate-config.js:
// karate-config.js
function fn() {
var config = { baseUrl: 'https://api.myapp.com' };
if (karate.env == 'ci') {
karate.configure('driver', { type: 'chrome', headless: true });
}
return config;
}Core UI actions
Karate UI provides a set of built-in step keywords for the most common browser interactions:
# Type text into an element
And input('#email', 'alice@test.com')
And input('#password', 'password123')
# Click a button or link
And click("button[type='submit']")
And click('.nav-link[href="/logout"]')
# Select from a dropdown
And select('#role-dropdown', 'Admin')
# Wait for an element to appear
And waitFor('#dashboard-header')
# Wait for URL to change
And waitForUrl('/dashboard')
# Assert on visible text
And match text('#welcome-message') contains 'Welcome, Alice'
# Assert on the page title
And match driver.title contains 'Dashboard'
# Take a screenshot (useful for debugging)
And screenshot()Selectors are CSS selectors — the same format used in Playwright and Cypress. If you've written UI tests with either of those tools, the selector syntax is immediately familiar.
A complete browser login flow
Feature: Login UI — Smoke Check
Scenario: Admin can log in and reach the dashboard
Given driver webAppUrl + '/login'
And input('#email', 'admin@test.com')
And input('#password', 'AdminPass1')
When click("button[type='submit']")
Then waitForUrl('/dashboard')
And match driver.title contains 'Dashboard'
And waitFor('.user-menu')
And match text('.user-menu') contains 'Alice'webAppUrl comes from karate-config.js — the same pattern as baseUrl for the API. The scenario is readable: open the login page, type credentials, click submit, wait for the dashboard, assert the title and a welcome element.
Combining API and UI in one scenario
The most distinctive Karate UI capability: API and browser steps in the same scenario, sharing variables:
Scenario: API creates a user, UI confirms they appear in the admin panel
# API step — create the user
Given url baseUrl
And path 'users'
And request { name: 'Alice Smith', email: 'alice@test.com', role: 'admin' }
When method post
Then status 201
* def userId = response.id
# UI step — verify the user appears in the admin panel
Given driver webAppUrl + '/admin/users'
And waitFor("[data-testid='user-row-" + userId + "']")
Then match text("[data-testid='user-row-" + userId + "']") contains 'Alice Smith'userId from the API response is used directly in the browser selector. No test framework bridge, no shared state mechanism — it's one variable in one scenario.
This pattern is useful for end-to-end verification: the API creates data, the UI confirms it renders correctly. It exercises the full stack from write to read to display.
When to use Karate UI vs dedicated UI tools
Karate UI vs dedicated browser automation frameworks
Karate UI
Same .feature file as API tests
Mix API calls and browser steps — share variables between them
Zero extra framework setup
If you already have Karate, browser automation is one config line
Good for: smoke checks, UI verification after API writes
Login smoke, user appears in admin, dashboard loads
Not ideal for: deep UI coverage, complex interactions
No component testing, no visual regression, limited assertion set
Playwright / Cypress
Purpose-built for browser testing
Network mocking, auto-wait, component isolation, visual diffs
Richer selector and assertion model
getByRole, getByText, toBeVisible, toHaveText, screenshots on failure
Better tooling for large UI suites
Trace viewer, video recording, parallel workers, test sharding
Good for: comprehensive UI testing, full regression suites
The right tool when UI coverage is a first-class requirement
Use Karate UI when the team is already on Karate and needs a handful of browser smoke checks alongside API tests. Use Playwright or Cypress when UI testing is a significant part of the test strategy — they have deeper tooling, better debugging, and a richer assertion model for complex interactions.
Karate UI is a bonus, not a replacement. It exists because some test scenarios naturally span both API and UI, and it handles those elegantly without requiring a separate framework.
⚠️ Common mistakes
- Using Karate UI as the primary UI testing tool for a large application. For 5 browser smoke checks, Karate UI is convenient. For 200 end-to-end UI scenarios, you'll hit its limits: no visual diff, no network interception, limited debugging tools compared to Playwright's trace viewer or Cypress's time-travel debugger. Choose the right tool for the scale.
- Not setting
headless: truein CI. Karate UI opens a real browser window by default. CI runners (GitHub Actions, Jenkins) don't have a display — running headed Chrome in CI fails immediately. Always addkarate.configure('driver', { type: 'chrome', headless: true })in thecienvironment branch ofkarate-config.js. - Sharing the browser session across scenarios. Karate UI creates a new browser session per scenario by default. If Scenario 1 logs in and sets a session cookie, Scenario 2 starts fresh — it's not logged in. This is the correct and safe behaviour. If you need a persistent session, use Background to open the browser and log in before each scenario, or investigate Karate's
configure(driver)session options for advanced cases.
🎯 Practice task
Write a browser smoke check and combine it with an API call. 35–45 minutes.
- Add
* def webAppUrl = 'https://the-internet.herokuapp.com'tokarate-config.js(a free public demo site for UI testing practice). - Write a scenario:
Given driver webAppUrl + '/login'. Typeadmininto#usernameandadmininto#password. Clickbutton[type='submit']. AssertwaitForUrl('/secure')andmatch driver.title contains 'The Internet'. Run it. This is your first Karate UI test. - Add
And screenshot()after the assertion. Open the screenshot file from the console output path. Confirm it shows the logged-in page. - Write a scenario on
https://the-internet.herokuapp.com/dropdown. Select option'Option 2'usingselect('#dropdown', 'Option 2'). Asserttext('#dropdown option:checked') == 'Option 2'. - Write a combined scenario: GET
https://jsonplaceholder.typicode.com/users/1(API call), extractresponse.nameintodef userName. Then opendriver webAppUrl + '/login'and add a comment showing where you would assertuserNameappears in a UI element — proving the variable is available in the browser step. - Add
karate.configure('driver', { type: 'chrome', headless: true })tokarate-config.jsunder acienvironment branch. Run with-Dkarate.env=ci. Confirm the browser runs without a visible window (no Chrome opens on your desktop). - Stretch: read the Karate UI documentation and find three actions you haven't used yet —
scroll,focus, orvalue. Write a short scenario that demonstrates each one against the Herokuapp demo pages.
Next chapter: reporting and CI/CD — reading the HTML report in detail, integrating with Cucumber reports, and running Karate in GitHub Actions.