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

getsnap

v1.14.0

Published

Official Node.js SDK + CLI for getSnap.dev — Screenshot & PDF API

Downloads

2,184

Readme

getsnap

Official Node.js SDK and CLI for getSnap.dev — Screenshot, PDF, and video API.

Installation

npm install getsnap

Command-line (npx getsnap)

Every install ships a getsnap executable. No code required for one-off captures:

# Set your key once
export GETSNAP_KEY=sk_live_YOUR_KEY

# Capture a PNG and print the CDN URL
npx getsnap screenshot https://news.ycombinator.com

# Save a binary directly to disk
npx getsnap screenshot https://news.ycombinator.com --out hn.png
npx getsnap pdf        https://news.ycombinator.com --out hn.pdf --full-page
npx getsnap og         https://blog.example.com/post --out og.png

# Video (MP4, 10 seconds, 15 fps by default)
npx getsnap video https://getsnap.dev --out demo.mp4 --duration 5

# Account info
npx getsnap usage
npx getsnap referrals

# Everything else
npx getsnap --help

Full flag reference: npx getsnap --help. Every capture flag maps 1:1 to the SDK option, so anything you can do with the JS SDK you can do from the CLI.

Quick Start (SDK)

import GetSnap from "getsnap";

const snap = new GetSnap("sk_live_YOUR_KEY");

// Take a screenshot
const { url } = await snap.screenshot({
  url: "https://github.com",
  format: "png",
  full_page: true,
  remove_popups: true,
});
console.log(url); // CDN URL to your screenshot

Features

  • Full TypeScript types for all options and responses
  • Screenshot capture (URL or HTML)
  • Binary response (raw image bytes)
  • Batch capture (up to 100 URLs)
  • Usage tracking
  • Async status polling
  • All API parameters supported: lazy_load, wait_for_selector, hide_selectors, remove_selectors, extract_text, extract_html, click_selector, scroll_to_selector, and more

API

new GetSnap(apiKey, options?)

Create a client instance.

  • apiKey — Your getSnap.dev key (starts with sk_live_ or sk_test_)
  • options.baseUrl — Custom base URL (default: https://api.getsnap.dev)

snap.screenshot(options)

Take a screenshot. Returns { url, cached, request_id, extracted_text?, extracted_html? }.

const result = await snap.screenshot({
  url: "https://example.com",
  format: "png",
  viewport_width: 1280,
  viewport_height: 720,
  full_page: true,
  remove_popups: true,
  block_ads: true,
  lazy_load: true,
  extract_text: true,
});

snap.screenshotBinary(options)

Get raw image/PDF bytes as an ArrayBuffer.

import { writeFile } from "fs/promises";

const buffer = await snap.screenshotBinary({
  url: "https://example.com",
  format: "webp",
  quality: 90,
});
await writeFile("screenshot.webp", Buffer.from(buffer));

snap.ogImage(options)

Generate a 1200×630 Open Graph / Twitter Card image from any URL. Applies social-share-optimized defaults on the server side (PNG, hi-DPI, wait for network idle, block popups + ads). Same billing as screenshot(): 1 credit per fresh capture, 0 credits for cache hits.

const { url } = await snap.ogImage({
  url: "https://blog.example.com/why-rust",
});
// Drop `url` directly into <meta property="og:image">

All defaults are overrideable (viewport_width, viewport_height, format, device_scale_factor, wait_for_selector, extra_delay_ms, block_ads, remove_popups, dark_mode, css). Pass response_type: "binary" to get raw bytes with Cache-Control: public, max-age=604800, immutable instead of a JSON URL.

snap.batch(options)

Capture multiple URLs in one request.

const batch = await snap.batch({
  urls: ["https://github.com", "https://stripe.com", "https://vercel.com"],
  format: "png",
  remove_popups: true,
});

console.log(`${batch.succeeded}/${batch.count} captured`);
batch.results.forEach(r => console.log(r.source_url, "->", r.url));

snap.usage()

Check current usage and quota.

const { used, limit, plan } = await snap.usage();
console.log(`${used}/${limit} (${plan})`);

snap.referrals()

Get your referral code, ready-to-share URL, reward tier, and aggregated stats. Every getSnap.dev account has a unique code auto-generated at signup — no opt-in required. When someone signs up through your referral URL and pays their first invoice, your Stripe balance is credited by the configured amount (default $5.00).

const r = await snap.referrals();
console.log(r.referral_url);
// https://getsnap.dev/?ref=USERABC1

console.log(`${r.stats.paid} paid, ${r.stats.pending} pending`);
console.log(`Lifetime earned: $${(r.stats.total_earned_cents / 100).toFixed(2)}`);

snap.diff(options)

Visual regression diff between two URLs. Captures both at identical dimensions, compares pixel-by-pixel with pixelmatch, returns before/after/diff URLs plus a similarity score (0-100).

Billed at 2 credits per fresh diff (1 per captured page). Cache hits on either side reduce the charge.

const r = await snap.diff({
  before: { url: "https://staging.example.com/pricing" },
  after:  { url: "https://example.com/pricing" },
});

console.log(`Similarity: ${r.similarity.toFixed(2)}%`);
if (r.similarity < 99) {
  console.log(`${r.changed_pixels} pixels changed - review:`, r.diff_url);
}

Per-side overrides for slower-loading pages:

await snap.diff({
  before: {
    url: "https://staging.example.com",
    wait_for_selector: "#pricing-table",  // wait for lazy content
    extra_delay_ms: 500,
  },
  after: {
    url: "https://example.com",
    css: "body { animation: none !important; }",  // freeze animations
  },
  viewport_width: 1440,
  threshold: 0.05,  // more sensitive than default 0.1
});

snap.audit(options)

Run an accessibility audit against a URL. Uses axe-core to evaluate WCAG 2.0 / 2.1 / 2.2 A/AA/AAA + Section 508 + best-practices rules and returns categorised violations, incomplete rules, pass counts, and (optionally) a screenshot.

Billed at 1 credit per audit + 1 more if include_screenshot: true.

const a = await snap.audit({ url: "https://example.com" });
console.log(a.summary);
// { total_violations: 2, critical: 0, serious: 0, moderate: 2, minor: 0 }

for (const v of a.violations.filter(v => v.impact === "critical")) {
  console.error(v.id, v.help, v.help_url);
}

snap.teams.* — team management

Share one plan, quota, and rate limit across multiple api_keys.

// Create a team - hoists your current plan onto the team
const team = await snap.teams.create({ name: "Acme Marketing" });

// Invite a member (owner/admin only)
const invite = await snap.teams.invite(team.id, { email: "[email protected]" });
console.log(`Accept URL: ${invite.accept_url}`);

// jane clicks the link, calls this from her own account:
const joined = await snap.teams.accept({ token: "<from-email>" });

// List members
const { members } = await snap.teams.members(team.id);
for (const m of members) {
  console.log(`${m.role}: ${m.email}`);
}

// List teams you're in
const { teams } = await snap.teams.list();

// Leave a team (owners cannot use this)
await snap.teams.leave(team.id);

Roles are owner / admin / member. Every team has exactly one owner. Only owners and admins can invite. Owners cannot leave via .leave() — they must transfer ownership or dissolve the team first.

snap.status(requestId)

Check status of an async (webhook) request.

const status = await snap.status("req_abc123");

Error Handling

import { GetSnap, GetSnapError } from "getsnap";

try {
  await snap.screenshot({ url: "https://example.com", format: "png" });
} catch (err) {
  if (err instanceof GetSnapError) {
    console.error(err.status, err.error, err.message);
    // 402, "quota_exceeded", "Monthly limit reached..."
  }
}

Migration from SnapAPI (v1.0.0)

The class was renamed from SnapAPI to GetSnap starting in v1.1.0. Both names still work — SnapAPI and SnapAPIError remain as aliases, so v1.0.0 code continues to compile without changes:

// still works
import { SnapAPI, SnapAPIError } from "getsnap";
const snap = new SnapAPI("sk_live_YOUR_KEY");

New code should prefer GetSnap and GetSnapError.

License

MIT