@olib-ai/owl-browser-sdk
v2.0.7
Published
Node.js SDK for Owl Browser automation - Async-first with dynamic OpenAPI method generation
Downloads
700
Maintainers
Readme
@olib-ai/owl-browser-sdk
Node.js SDK v2 for Owl Browser - AI-native browser automation with antidetect capabilities.
Features
- Async-first design - All operations are async/await based
- Dynamic method generation - 144+ browser tools available as typed methods
- OpenAPI schema bundled - Works offline, no need to fetch schema from server
- Flow execution engine - Run complex automation flows with conditions and expectations
- JWT and Token auth - Flexible authentication options
- TypeScript support - Full type definitions included
- Retry with backoff - Built-in retry logic with exponential backoff and jitter
Installation
npm install @olib-ai/owl-browser-sdkQuick Start
import { OwlBrowser, RemoteConfig } from '@olib-ai/owl-browser-sdk';
const browser = new OwlBrowser({
url: 'http://localhost:8080',
token: 'your-secret-token',
apiPrefix: '' // Use '' for direct connection, '/api' for nginx proxy
});
await browser.connect();
// Create a context
const ctx = await browser.createContext();
const contextId = ctx.context_id;
// Navigate to a page
await browser.navigate({ context_id: contextId, url: 'https://example.com' });
// Click an element
await browser.click({ context_id: contextId, selector: 'button#submit' });
// Take a screenshot
const screenshot = await browser.screenshot({ context_id: contextId });
// Close the context
await browser.closeContext({ context_id: contextId });
await browser.close();Configuration
RemoteConfig Options
interface RemoteConfig {
// Required
url: string; // Server URL (e.g., 'http://localhost:8080')
// Authentication (one required)
token?: string; // Bearer token for TOKEN auth
authMode?: AuthMode; // 'token' (default) or 'jwt'
jwt?: JWTConfig; // JWT configuration for JWT auth
// Optional
transport?: TransportMode; // 'http' (default) or 'websocket'
timeout?: number; // Request timeout in seconds (default: 30)
maxConcurrent?: number; // Max concurrent requests (default: 10)
retry?: RetryConfig; // Retry configuration
verifySsl?: boolean; // Verify SSL certificates (default: true)
apiPrefix?: string; // API prefix (default: '/api', use '' for direct)
}JWT Authentication
import { OwlBrowser, AuthMode } from '@olib-ai/owl-browser-sdk';
const browser = new OwlBrowser({
url: 'http://localhost:8080',
authMode: AuthMode.JWT,
jwt: {
privateKeyPath: '/path/to/private.pem',
expiresIn: 3600, // Token validity in seconds
refreshThreshold: 300, // Refresh when < 300s remaining
issuer: 'my-app',
claims: { custom: 'data' }
}
});Dynamic Methods
The SDK dynamically generates methods for all 144+ browser tools. Methods are available in both camelCase and snake_case:
// These are equivalent
await browser.createContext();
await browser.create_context();
// Navigation
await browser.navigate({ context_id: ctx, url: 'https://example.com' });
await browser.reload({ context_id: ctx });
await browser.goBack({ context_id: ctx });
await browser.goForward({ context_id: ctx });
// Interaction
await browser.click({ context_id: ctx, selector: '#button' });
await browser.type({ context_id: ctx, selector: '#input', text: 'Hello' });
await browser.scroll({ context_id: ctx, direction: 'down' });
// Data extraction
await browser.getHtml({ context_id: ctx });
await browser.getMarkdown({ context_id: ctx });
await browser.screenshot({ context_id: ctx });
// AI-powered tools
await browser.queryPage({ context_id: ctx, question: 'What is the title?' });
await browser.solveCaptcha({ context_id: ctx });
await browser.findElement({ context_id: ctx, description: 'login button' });Flow Execution
Execute complex automation flows with variable resolution and expectations:
import { OwlBrowser, FlowExecutor } from '@olib-ai/owl-browser-sdk';
const browser = new OwlBrowser({ url: '...', token: '...' });
await browser.connect();
const ctx = await browser.createContext();
const executor = new FlowExecutor(browser, ctx.context_id);
// Load flow from JSON file
const flow = FlowExecutor.loadFlow('test-flows/navigation.json');
const result = await executor.execute(flow);
if (result.success) {
console.log('Flow completed in', result.totalDurationMs, 'ms');
} else {
console.error('Flow failed:', result.error);
}Flow JSON Format
{
"name": "Login Flow",
"description": "Automates login process",
"steps": [
{
"type": "browser_navigate",
"url": "https://example.com/login"
},
{
"type": "browser_type",
"selector": "#email",
"text": "[email protected]"
},
{
"type": "browser_type",
"selector": "#password",
"text": "secret123"
},
{
"type": "browser_click",
"selector": "#submit",
"expected": {
"notEmpty": true
}
},
{
"type": "browser_wait_for_selector",
"selector": ".dashboard",
"expected": {
"equals": true,
"field": "found"
}
}
]
}Variable Resolution
Use ${prev} to reference previous step results:
{
"steps": [
{
"type": "browser_evaluate",
"script": "document.querySelector('.user-id').textContent"
},
{
"type": "browser_navigate",
"url": "https://example.com/users/${prev}"
}
]
}Supported syntax:
${prev}- Entire previous result${prev.field}- Field in previous result${prev[0]}- Array element${prev[0].id}- Nested access
Expectations
Validate step results:
const expectation = {
equals: 'expected value', // Exact match
contains: 'substring', // String contains
length: 5, // Array/string length
greaterThan: 10, // Numeric comparison
lessThan: 100, // Numeric comparison
notEmpty: true, // Not null/empty
matches: '^[A-Z]+$', // Regex pattern
field: 'data.items' // Nested field to check
};Conditional Branching
{
"type": "condition",
"condition": {
"source": "previous",
"operator": "equals",
"field": "success",
"value": true
},
"onTrue": [
{ "type": "browser_click", "selector": "#continue" }
],
"onFalse": [
{ "type": "browser_screenshot" }
]
}Playwright-Compatible API
Drop-in Playwright API that translates Playwright calls to Owl Browser tools. Use your existing Playwright code with Owl Browser's antidetect capabilities.
import { chromium, devices } from '@olib-ai/owl-browser-sdk/playwright';
const browser = await chromium.connect('http://localhost:8080', { token: 'your-token' });
const context = await browser.newContext(devices['iPhone 15 Pro']);
const page = await context.newPage();
await page.goto('https://example.com');
await page.click('button#submit');
await page.fill('#search', 'query');
const text = await page.textContent('h1');
const screenshot = await page.screenshot({ path: 'page.png' });
// Locators
const button = page.locator('button.primary');
await button.click();
// Playwright-style selectors
const login = page.getByRole('button', { name: 'Log in' });
const input = page.getByPlaceholder('Enter email');
const heading = page.getByText('Welcome');
await context.close();
await browser.close();Supported features: Page navigation, click/fill/type/press, locators (CSS, text, role, test-id, xpath), frames, keyboard & mouse input, screenshots, network interception (route/unroute), dialogs, downloads, viewport emulation, and 20+ device descriptors (iPhone, Pixel, Galaxy, iPad, Desktop).
Data Extraction
Universal structured data extraction from any website — CSS selectors, auto-detection, tables, metadata, and multi-page scraping with pagination. No AI dependencies, works deterministically with cheerio.
import { OwlBrowser } from '@olib-ai/owl-browser-sdk';
import { Extractor } from '@olib-ai/owl-browser-sdk/extraction';
const browser = new OwlBrowser({ url: '...', token: '...' });
await browser.connect();
const ctx = await browser.createContext();
const ex = new Extractor(browser, ctx.context_id);
await ex.goto('https://example.com/products');
// CSS selector extraction
const products = await ex.select('.product-card', {
name: 'h3',
price: '.price',
image: 'img@src',
link: 'a@href',
});
// Auto-detect repeating patterns (zero-config)
const patterns = await ex.detect();
// Multi-page scraping with automatic pagination
const result = await ex.scrape('.product-card', {
fields: { name: 'h3', price: '.price', sku: '@data-sku' },
maxPages: 10,
deduplicateBy: 'sku',
});
console.log(`${result.totalItems} items from ${result.pagesScraped} pages`);Capabilities:
| Method | Description |
|--------|-------------|
| select() / selectFirst() | Extract with CSS selectors and field specs ("selector", "selector@attr", object specs with transforms) |
| table() / grid() / definitionList() | Parse <table>, CSS grid/flexbox, and <dl> structures |
| meta() / jsonLd() | Extract OpenGraph, Twitter Card, JSON-LD, microdata, feeds |
| detect() / detectAndExtract() | Auto-discover repeating DOM patterns |
| lists() | Extract list/card containers with auto-field inference |
| scrape() | Multi-page with pagination detection (click-next, URL patterns, buttons, load-more, infinite scroll) |
| clean() | Remove cookie banners, modals, fixed elements, ads |
| html() / markdown() / text() | Raw content with cleaning levels |
All extraction functions are also available as standalone pure functions for use without a browser connection.
Error Handling
import {
OwlBrowserError,
ConnectionError,
AuthenticationError,
ToolExecutionError,
TimeoutError,
RateLimitError,
ElementNotFoundError
} from '@olib-ai/owl-browser-sdk';
try {
await browser.click({ context_id: ctx, selector: '#nonexistent' });
} catch (e) {
if (e instanceof ElementNotFoundError) {
console.log('Element not found:', e.selector);
} else if (e instanceof TimeoutError) {
console.log('Operation timed out after', e.timeoutMs, 'ms');
} else if (e instanceof RateLimitError) {
console.log('Rate limited. Retry after', e.retryAfter, 'seconds');
} else if (e instanceof AuthenticationError) {
console.log('Auth failed:', e.message);
}
}Advanced Usage
Direct Transport Access
import { HTTPTransport, WebSocketTransport } from '@olib-ai/owl-browser-sdk';
// Use HTTP transport directly
const transport = new HTTPTransport({
url: 'http://localhost:8080',
token: 'secret'
});
await transport.connect();
const result = await transport.execute('browser_navigate', {
context_id: 'ctx_1',
url: 'https://example.com'
});
await transport.close();OpenAPI Schema Access
import { OpenAPILoader, getBundledSchema } from '@olib-ai/owl-browser-sdk';
// Get bundled schema
const schema = getBundledSchema();
console.log('API Version:', schema.info.version);
// Load and parse schema
const loader = new OpenAPILoader(schema);
for (const [name, tool] of loader.tools) {
console.log(name + ':', tool.description);
}API Reference
OwlBrowser
connect(): Promise<void>- Connect to serverclose(): Promise<void>- Close connectionexecute(toolName, params): Promise<unknown>- Execute any toolhealthCheck(): Promise<HealthResponse>- Check server healthlistTools(): string[]- List all tool nameslistMethods(): string[]- List all method namesgetTool(name): ToolDefinition | undefined- Get tool definition
FlowExecutor
execute(flow): Promise<FlowResult>- Execute a flowabort(): void- Abort current executionreset(): void- Reset abort flagstatic loadFlow(path): Flow- Load flow from JSON filestatic parseFlow(data): Flow- Parse flow from object
Extractor
goto(url, options?): Promise<void>- Navigate to URLselect(selector, fields): Promise<Record[]>- Extract from all matchesselectFirst(selector, fields): Promise<Record | null>- Extract first matchcount(selector): Promise<number>- Count matching elementstable(selector?, options?): Promise<Record[]>- Parse HTML tablesgrid(container, item?): Promise<Record[]>- Parse CSS gridsdefinitionList(selector?): Promise<Record>- Parse<dl>listsdetectTables(): Promise<TableInfo[]>- Auto-detect tablesmeta(): Promise<MetaData>- Extract page metadatajsonLd(): Promise<object[]>- Extract JSON-LDdetect(options?): Promise<DetectedPattern[]>- Detect repeating patternsdetectAndExtract(options?): Promise<Record[]>- Detect + extractlists(selector, options?): Promise<Record[]>- Extract lists/cardsscrape(selector, options?): Promise<ExtractionResult>- Multi-page scrapeabortScrape(): void- Abort running scrapeclean(options?): Promise<CleanResult>- Remove obstructionshtml(options?): Promise<string>- Get page HTMLmarkdown(): Promise<string>- Get page markdowntext(selector?, regex?): Promise<string>- Get filtered textdetectSite(): Promise<string>- Detect site typesiteData(template?): Promise<unknown>- Site-specific extraction
Requirements
- Node.js 18+
- TypeScript 5+ (optional, for type definitions)
License
MIT - See LICENSE file for details.
Links
- Website: https://www.owlbrowser.net
- Documentation: https://www.owlbrowser.net/docs
- GitHub: https://github.com/Olib-AI/olib-browser
- Support: [email protected]
