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

@certscore/sdk

v0.2.6

Published

Official TypeScript SDK for the CertScore Pulse API.

Readme

CertScore TypeScript SDK

Official TypeScript/JavaScript SDK for the CertScore public API, Pulse API, and website risk-signal workflows.

CertScore outputs are automated public-web observations for review. They are not legal advice, certification, or a compliance determination. Always review the underlying evidence and consult qualified experts where appropriate.

Status

The SDK is published as @certscore/sdk on npm. Use version 0.2.6 or newer for typed no-account allowance and higher-volume support guidance, completed-limited no-go results, API v2 scan timing fields, and client attribution headers. See the npm package and SDK source.

npm install @certscore/sdk

By default the SDK identifies its requests with X-CertScore-Client: sdk. The optional clientName setting is intended for trusted integrations that share the SDK runtime with MCP; regular SDK consumers should keep the default.

Completed no-go scans resolve normally with status: "completed_limited", resultDisposition: "no_go", and a typed noGo object. The object carries a stable reason, customer-safe explanation, target-site or scanner-limitation attribution through limitationKind, retry guidance, and a bounded evidenceExcerpt when available.

Quick Start

import { CertScoreClient } from "@certscore/sdk";

const client = new CertScoreClient();
const pulse = await client.scan("https://example.com");
console.log(pulse.summary?.score, pulse.links?.fullReportUrl);

Resource Clients

New integrations should prefer the resource-oriented API v2 clients for scan, status, finding, pre-consent cookie/tracker table, domain latest, and Pulse projection workflows.

import { CertScoreClient } from "@certscore/sdk";

const certscore = new CertScoreClient({
  apiKey: process.env.CERTSCORE_API_KEY
});

const created = await certscore.scans.create("https://example.com", {
  freshness: "latest",
  scanFrom: "eu_ie"
});

const completed = await certscore.scans.wait(created);
const scanId = completed.scanId;

const status = await certscore.scans.status(scanId);
const diagnostics = await certscore.scans.diagnostics(scanId);
const findings = await certscore.findings.list(scanId);
const preConsentTable = await certscore.scans.preConsentCookiesTrackers(scanId);
const firstFinding = findings.findings[0]
  ? await certscore.findings.get(scanId, findings.findings[0].id)
  : null;
const explanation = firstFinding
  ? await certscore.findings.explain(scanId, firstFinding.id)
  : null;
const pulseProjection = await certscore.pulse.get(scanId);
const pulseEvidence = await certscore.pulse.evidence(scanId);
const latestDomainScan = await certscore.domains.latest("example.com");
const latestPreConsentTable = await certscore.domains.latestPreConsentCookiesTrackers("example.com");

console.log(status.status, diagnostics.totalWallMs, diagnostics.policyDiscovery.phaseWallMs, preConsentTable.summary.rowCount, explanation?.title, pulseProjection.disclaimer, pulseEvidence.type, latestDomainScan.scan?.scanId, latestPreConsentTable.rows.length);

certscore.scans.get(), certscore.scans.status(), and certscore.scans.wait() expose scan timing where the API has enough evidence:

  • startedAt
  • completedAt
  • scanTimeSeconds

scanTimeSeconds is null when timing is unavailable or incomplete. Client code should not coerce that value to 0; reserve 0 only for an explicit numeric API value.

Available resource clients:

  • certscore.scans.create()
  • certscore.scans.diagnostics()
  • certscore.scans.get()
  • certscore.scans.preConsentCookiesTrackers()
  • certscore.scans.status()
  • certscore.scans.wait()
  • certscore.findings.list()
  • certscore.findings.get()
  • certscore.findings.explain()
  • certscore.pulse.get()
  • certscore.pulse.evidence()
  • certscore.domains.latest()
  • certscore.domains.latestPreConsentCookiesTrackers()
  • certscore.scan()

Cookies & Trackers (Pre-consent)

Use the API v2 resource client when you need the public report table as JSON instead of parsing report HTML or Pulse prose.

const table = await certscore.scans.preConsentCookiesTrackers(scanId);

const grouped = new Map<string, typeof table.rows>();
for (const row of table.rows) {
  const key = [row.vendor, row.purpose, row.host].join("|");
  grouped.set(key, [...(grouped.get(key) ?? []), row]);
}

const latestTable = await certscore.domains.latestPreConsentCookiesTrackers("example.com");
console.log(grouped.size, latestTable.summary.rowCount);

The response is a public-safe report projection. It does not include cookie values, raw request bodies, full request URLs, sensitive query strings, or internal scanner artifacts. Server-side filters are intentionally deferred in the initial version; group or filter the returned table client-side by kind, priority, party, vendor, purpose, or host.

Async Lifecycle

scan() calls /api/v1/pulse with wait=60. If CertScore returns HTTP 202, the SDK polls the returned statusUrl or nextCheckUrl. It honors Retry-After on pending or throttled responses.

import { CertScoreClient, CertScoreTimeoutError } from "@certscore/sdk";

const client = new CertScoreClient();

try {
  const pulse = await client.scan("https://example.com", {
    detail: "standard",
    maxWaitMs: 300_000,
    // Omit for adaptive 1s → 2s → 5s polling; set explicitly for a fixed interval.
    onStatusUpdate(status) {
      console.log("Pulse status:", status.status, status.phase);
    }
  });

  if (pulse.scanStatus === "completed" || pulse.scanStatus === "completed_limited") {
    console.log("Result:", pulse.summary?.headline);
  }
} catch (error) {
  if (error instanceof CertScoreTimeoutError) {
    console.log("Resume later with:", error.jobId, error.scanId);
  } else {
    throw error;
  }
}

Durable scanId Pattern

scanId is the durable audit/cache handle. scan_id may appear in API responses as a compatibility alias, but new integrations should store scanId.

const pulse = await client.scan("https://example.com");
const scanId = pulse.scanId;

await appDb.pulseScans.upsert({
  domain: "example.com",
  scanId,
  reportUrl: pulse.links?.fullReportUrl
});

// Later:
const cachedPulse = await client.getScan(scanId!, { detail: "full" });

Use the full report URL for human review:

console.log(`https://certscore.ai/scan/${scanId}`);

Error Handling

import {
  CertScoreApiError,
  CertScoreClient,
  CertScoreScanFailedError,
  CertScoreTimeoutError,
  InvalidUrlError,
  ThrottledError
} from "@certscore/sdk";

const client = new CertScoreClient();

try {
  await client.scan("https://example.com", { freshness: "refresh" });
} catch (error) {
  if (error instanceof InvalidUrlError) {
    console.error("Invalid URL:", error.message);
  } else if (error instanceof ThrottledError) {
    console.error("Retry after seconds:", error.retryAfterSeconds);
  } else if (error instanceof CertScoreTimeoutError) {
    console.error("Timed out; resume with:", error.jobId, error.scanId);
  } else if (error instanceof CertScoreScanFailedError) {
    console.error("Scan ended before completion:", error.jobId, error.scanId);
  } else if (error instanceof CertScoreApiError) {
    console.error("API error:", error.status, error.code, error.responseBody);
  } else {
    throw error;
  }
}

Markdown Output

Markdown is useful for agent or human-facing summaries.

const markdown = await client.scan("https://example.com", {
  format: "markdown",
  detail: "standard"
});

console.log(markdown);

Submit Without Polling

const job = await client.submitScan("https://example.com", {
  detail: "tiny"
});

console.log(job.status, job.jobId, job.scanId, job.statusUrl);

CI/CD Example

Example GitHub Actions workflow:

name: CertScore Pulse

on:
  deployment_status:

jobs:
  pulse:
    if: github.event.deployment_status.state == 'success'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: node scripts/certscore-pulse-check.mjs
        env:
          TARGET_URL: https://example.com

Example scripts/certscore-pulse-check.mjs:

import { CertScoreClient } from "@certscore/sdk";

const client = new CertScoreClient();
const pulse = await client.scan(process.env.TARGET_URL, {
  detail: "standard"
});

const criticalFindings = (pulse.topFindings ?? []).filter(
  (finding) => finding.criticality === "critical"
);

if (criticalFindings.length > 0) {
  console.error("CertScore surfaced critical automated review signals:");
  for (const finding of criticalFindings) {
    console.error(`- ${finding.label ?? finding.id}`);
  }
  process.exit(1);
}

console.log("No critical automated review signals were surfaced in this Pulse.");

This CI example fails only on critical automated review signals surfaced by CertScore. It does not make a legal or compliance conclusion. CertScore provides automated public-web observations for review, not legal advice, certification, or a compliance determination.

API Notes

  • detail supports tiny, quick, standard, and full; quick is an alias for tiny.
  • format supports json and markdown.
  • freshness supports latest and refresh.
  • wait accepts 0 to 80 seconds and only controls the current HTTP request hold window.
  • HTTP 202 and 429 may include Retry-After; the SDK uses it for polling/retry timing.
  • Terminal usable statuses are completed and completed_limited.
  • Terminal edge statuses include failed, expired, and rate_limited.