If you've been using WebdriverIO for API testing, you know the pain — every test spins up a browser session even when you're just hitting REST endpoints. That's wasted time, memory, and CI minutes. wdio-api-runner solves this by bypassing browser session creation entirely, giving you the full power of WebdriverIO's test orchestration for pure API and backend testing.

Why wdio-api-runner?

Traditional WebdriverIO testing creates browser sessions for every test, even when you're just testing APIs. Here's how the API runner compares:

MetricBrowser RunnerAPI Runner
Startup time~2-5 seconds~50ms
Memory per worker~200-500MB~30MB
DependenciesBrowser + DriverNone
CI/CD complexityHighMinimal

Features

  • Zero Browser Overhead — No WebDriver, no browser binaries, no session management
  • Native Fetch API Client — Modern, Promise-based HTTP client with full TypeScript support
  • Fluent Assertions — Chain assertions for status, headers, body, and JSON schema validation
  • Authentication Helpers — Built-in Basic, API Key, Bearer/JWT, and OAuth2 support
  • GraphQL Support — Full support for queries, mutations, and subscriptions
  • HAR Logging — Record requests to HAR format for debugging and replay
  • Performance Metrics — p50/p95/p99 latency tracking with threshold checking
  • All WDIO Features — Parallel execution, reporters, services, and frameworks work seamlessly

Installation

npm install wdio-api-runner --save-dev

Quick Start

Step 1: Configure WebdriverIO

Set runner: 'api' in your WebdriverIO config file — that's the key change. Everything else stays familiar:

// wdio.conf.ts
export const config: WebdriverIO.Config = {
    runner: 'api',
    specs: ['./test/api/**/*.spec.ts'],
    framework: 'mocha',
    reporters: ['spec'],
    baseUrl: 'https://api.example.com',

    apiRunner: {
        timeout: 30000,
        headers: {
            'Content-Type': 'application/json'
        }
    }
}

Step 2: Write Your First Test

The api object is globally available in your tests, providing familiar HTTP methods:

describe('Users API', () => {
    it('should fetch user by ID', async () => {
        const response = await api.get('/users/1')

        expect(response.status).toBe(200)
        expect(response.data).toHaveProperty('id', 1)
        expect(response.data).toHaveProperty('email')
    })

    it('should create a new user', async () => {
        const response = await api.post('/users', {
            name: 'John Doe',
            email: 'john@example.com'
        })

        expect(response.status).toBe(201)
    })
})

Step 3: Run Your Tests

npx wdio run wdio.conf.ts

That's it — no browser downloads, no driver setup, just fast API tests.

Fluent Assertions

One of the most powerful features is the fluent assertion API. Chain multiple assertions for readable, expressive test code:

import { assertResponse } from 'wdio-api-runner'

assertResponse(response)
    .toBeSuccess()
    .and.toHaveContentType('application/json')
    .and.toHaveBodyProperty('users')
    .and.toRespondWithin(500)

This is much cleaner than writing individual expect() statements for each check. The chain reads like a specification.

Authentication

Real-world APIs need authentication. The runner provides built-in helpers for common auth patterns:

Bearer Token

import { bearerAuth } from 'wdio-api-runner'

api.addRequestInterceptor(bearerAuth({
    token: async () => await getToken()
}).interceptor)

OAuth2 Client Credentials

import { oauth2ClientCredentials } from 'wdio-api-runner'

api.addRequestInterceptor(oauth2ClientCredentials({
    tokenUrl: 'https://auth.example.com/token',
    clientId: 'my-client',
    clientSecret: 'secret'
}).interceptor)

The auth helpers handle token refresh, caching, and retry logic automatically — you don't need to manage tokens manually in your tests.

GraphQL Support

For teams working with GraphQL APIs, the runner includes a dedicated GraphQL client:

import { createGraphQLClient } from 'wdio-api-runner'

const graphql = createGraphQLClient({
    endpoint: 'https://api.example.com/graphql'
})

const response = await graphql.query(`
    query GetUser($id: ID!) {
        user(id: $id) { id name email }
    }
`, { id: '123' })

The GraphQL client supports queries, mutations, and subscriptions with full TypeScript type inference.

Performance Metrics

The API runner tracks response times automatically. You can set thresholds and get p50/p95/p99 latency metrics:

// Assert response time is within threshold
assertResponse(response).toRespondWithin(500)

// Track metrics across multiple requests
const metrics = api.getPerformanceMetrics()
console.log(metrics.p95) // 95th percentile latency

CI Integration

Since there are no browser dependencies, CI integration is dramatically simpler. No need for Chrome/Firefox binaries, no Xvfb for headless mode, no driver management:

# GitHub Actions example
jobs:
  api-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 18
      - run: npm ci
      - run: npx wdio run wdio.conf.ts

That's a complete CI pipeline for API tests — no Docker containers, no browser setup, no complexity.

When to Use wdio-api-runner

Use the API runner when you:

  • Have a dedicated API/backend test suite separate from UI tests
  • Want to reuse WebdriverIO's ecosystem (reporters, services, parallel execution) for API testing
  • Need fast feedback loops in CI — startup in ~50ms vs ~2-5 seconds
  • Want consistent tooling between your UI and API test teams
  • Are testing microservices, GraphQL APIs, or REST endpoints

Keep the browser runner for tests that actually need a browser — UI tests, visual regression, and E2E flows that involve both UI and API interactions.

Full Documentation

This post covers the basics. For the full documentation including advanced configuration, custom interceptors, HAR logging, and more, visit the official documentation site.

You can also find the source code and contribute on GitHub.


Have questions about setting up wdio-api-runner? Feel free to reach out or open an issue on GitHub.