npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

browsecraft

v0.6.3

Published

AI-native browser automation framework. Craft browser tests that just work.

Downloads

1,158

Readme

Browsecraft

Browser automation that just works.

import { Browser } from 'browsecraft';

const browser = await Browser.launch();
const page = await browser.newPage();

await page.goto('https://www.saucedemo.com');
await page.fill('Username', 'standard_user');
await page.fill('Password', 'secret_sauce');
await page.click('Login');

await page.waitForURL('inventory');
console.log(await page.title()); // "Swag Labs"

await browser.close();

No CSS selectors. No XPath. Just tell it what you see on the page.

Install

npm install browsecraft

Requires Node.js 20+ and Chrome, Edge, or Firefox installed on your machine.

Quick Start

Create a file called test.mjs:

import { Browser } from 'browsecraft';

const browser = await Browser.launch();
const page = await browser.newPage();

await page.goto('https://example.com');
console.log(await page.title()); // "Example Domain"

const screenshot = await page.screenshot();
const { writeFileSync } = await import('node:fs');
writeFileSync('screenshot.png', screenshot);

await browser.close();

Run it:

node test.mjs

That's it. No config files, no test runner setup, no boilerplate.

API

Launch a browser

import { Browser } from 'browsecraft';

const browser = await Browser.launch({
  browser: 'chrome',   // 'chrome' | 'firefox' | 'edge' (default: 'chrome')
  headless: true,       // default: true
  maximized: false,     // maximize the window (headed mode only)
});

const page = await browser.newPage();
// ... do things ...
await browser.close();

Navigate

await page.goto('https://example.com');

const url = await page.url();
const title = await page.title();
const html = await page.content();

Click

// By visible text — Browsecraft finds the element for you
await page.click('Submit');
await page.click('Add to cart');

// By CSS selector — when you need precision
await page.click({ selector: '[data-test="login-button"]' });

Fill in fields

// By label or placeholder text
await page.fill('Username', 'standard_user');
await page.fill('Password', 'secret_sauce');

// By CSS selector
await page.fill({ selector: '#email' }, '[email protected]');

Wait for things

await page.waitForURL('dashboard');              // URL contains "dashboard"
await page.waitForURL(/checkout/);               // URL matches regex
await page.waitForSelector({ selector: '.loaded' }); // element appears

Find elements

const el = await page.get({ selector: '.product-card' });
const btn = await page.getByText('Add to Cart');

await el.textContent();
await el.isVisible();
await el.getAttribute('href');

Read text from the page

const text = await page.innerText({ selector: '.message' });

Run JavaScript in the browser

const count = await page.evaluate('document.querySelectorAll(".item").length');
const data = await page.evaluate('({ name: "test", items: [1, 2, 3] })');

Screenshots

const buffer = await page.screenshot(); // returns PNG Buffer

import { writeFileSync } from 'node:fs';
writeFileSync('screenshot.png', buffer);

Cookies

await page.getCookies();
await page.clearCookies();

Multiple tabs

const page1 = await browser.newPage();
const page2 = await browser.newPage();

browser.openPages;   // [page1, page2]
browser.isConnected; // true

await page1.close();
await page2.close();
await browser.close();

BDD Testing

Browsecraft has a built-in BDD framework. No Cucumber, no third-party dependencies — everything is custom-built.

There are two ways to write BDD tests:

Option 1: Gherkin .feature files

Write scenarios in plain English, then wire them to code with step definitions.

features/login.feature

Feature: User Login

  Scenario: Successful login
    Given I am on the login page
    When I fill "Username" with "standard_user"
    And I fill "Password" with "secret_sauce"
    And I click "Login"
    Then I should see "Products"

test.mjs

import { readFileSync } from 'node:fs';
import { Browser } from 'browsecraft';
import {
  parseGherkin, Given, When, Then,
  BddExecutor, globalRegistry,
} from 'browsecraft-bdd';

// --- Step definitions ---
// Each Given/When/Then matches a line in the .feature file.
// {string} captures a quoted argument.

Given('I am on the login page', async (world) => {
  await world.page.goto('https://www.saucedemo.com');
});

When('I fill {string} with {string}', async (world, field, value) => {
  await world.page.fill(field, value);
});

When('I click {string}', async (world, text) => {
  await world.page.click(text);
});

Then('I should see {string}', async (world, text) => {
  const content = await world.page.content();
  if (!content.includes(text)) throw new Error(`Expected "${text}" on page`);
});

// --- Run ---

const browser = await Browser.launch();
const doc = parseGherkin(readFileSync('features/login.feature', 'utf-8'));

const executor = new BddExecutor({
  registry: globalRegistry,
  worldFactory: async () => ({
    page: await browser.newPage(),
    browser,
    ctx: {},
    attach: () => {},
    log: console.log,
  }),
});

const result = await executor.runDocument(doc);
console.log(`${result.summary.scenarios.passed}/${result.summary.scenarios.total} passed`);
await browser.close();

Option 2: TypeScript-native BDD

Same structured BDD output, but no .feature files — write everything in code.

import { Browser } from 'browsecraft';
import { feature, scenario, given, when, then, runFeatures } from 'browsecraft-bdd';

feature('User Login', () => {
  scenario('Successful login', ({ page }) => {
    given('I am on the login page', () =>
      page.goto('https://www.saucedemo.com'));

    when('I enter credentials and log in', async () => {
      await page.fill('Username', 'standard_user');
      await page.fill('Password', 'secret_sauce');
      await page.click('Login');
    });

    then('I should see the products page', () =>
      page.waitForURL('inventory'));
  });
});

const browser = await Browser.launch();
const result = await runFeatures({
  worldFactory: async () => ({
    page: await browser.newPage(),
    browser,
    ctx: {},
    attach: () => {},
    log: console.log,
  }),
});
console.log(`${result.summary.scenarios.passed}/${result.summary.scenarios.total} passed`);
await browser.close();

Tags

Filter which scenarios run using tag expressions:

@smoke
Scenario: Quick test
  ...

@slow @integration
Scenario: Full flow
  ...
const executor = new BddExecutor({
  tagFilter: '@smoke and not @slow',
  // ...
});

Supports and, or, not, and parentheses.

Hooks

import { Before, After, BeforeAll, AfterAll } from 'browsecraft-bdd';

BeforeAll(async () => { /* one-time setup */ });
AfterAll(async () => { /* one-time teardown */ });
Before(async (ctx) => { /* before each scenario */ });
After(async (ctx) => { /* after each scenario */ });

Gherkin parser features

The built-in parser handles the full Gherkin spec:

  • Scenario Outlines with Examples tables
  • Background steps
  • Data Tables and Doc Strings
  • Tags on features and scenarios
  • Rules
  • Comments
  • Multiple languages (English, Spanish, French, German, Japanese, and more)

AI Features (Optional)

AI features use the GitHub Models API — free with any GitHub account. Set a PAT with the models scope:

export GITHUB_TOKEN=ghp_...

Everything works without AI. These features enhance the experience when available.

| Feature | What it does | | --- | --- | | Self-healing selectors | When a CSS selector breaks, suggests a replacement using page context | | AI failure diagnosis | Analyzes failures with page context and suggests fixes | | Test generation | Generates test code from a natural-language description | | Visual regression | Compares screenshots pixel-by-pixel, with optional AI semantic analysis | | Auto-step generation | Writes BDD step definitions from .feature files automatically | | Persistent AI cache | Caches AI results on disk to avoid redundant API calls |

import { healSelector, generateTest, compareScreenshots, diagnoseFailure } from 'browsecraft-ai';

Examples

The examples/ directory has complete, runnable projects you can copy as a starting point:

| Example | What it shows | | --- | --- | | getting-started/ | Imperative tests — login, cart, checkout, screenshots | | bdd-gherkin/ | .feature files with step definitions (9 scenarios) | | bdd-typescript/ | TypeScript-native BDD with feature()/scenario() (6 scenarios) |

All examples test against the Sauce Labs Demo App (public, no account needed):

cd examples/getting-started
npm install
node test.mjs              # headless
node test.mjs --headed     # watch it run
node test.mjs --maximized  # full screen

Architecture

Six npm packages, one monorepo:

| Package | Role | | --- | --- | | browsecraft | Main package. Page API, Browser, config, CLI, adaptive timing, self-healing. | | browsecraft-bdd | Gherkin parser, step registry, executor, hooks, tags, TS-native BDD, 38 built-in steps, AI auto-steps. | | browsecraft-bidi | WebDriver BiDi protocol client and browser launcher. | | browsecraft-runner | Event bus, multi-browser worker pool, parallel scheduler, result aggregator, failure classification, smart retry. | | browsecraft-ai | Self-healing selectors, AI failure diagnosis, test generation, visual diff, persistent cache. | | create-browsecraft | Project scaffolding CLI (npm init browsecraft). Zero dependencies. |

Most users only need browsecraft. Add browsecraft-bdd for BDD, browsecraft-ai for AI features.

Built on the W3C WebDriver BiDi protocol — controls real, unpatched browser binaries. No special builds, no browser extensions.

License

MIT