
Product
Socket for ClickUp Is Now Available
Create ClickUp tasks from Socket alerts, automate ticketing with custom rules, and keep alert and task status synchronized.
@certscore/sdk
Advanced tools
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.
The SDK is published as @certscore/sdk on npm. Use version 0.2.3 or newer when you need API v2 scan timing fields.
npm install @certscore/sdk
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);
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 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, 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:
startedAtcompletedAtscanTimeSecondsscanTimeSeconds 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.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()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.
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,
pollIntervalMs: 5_000,
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;
}
}
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}`);
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 is useful for agent or human-facing summaries.
const markdown = await client.scan("https://example.com", {
format: "markdown",
detail: "standard"
});
console.log(markdown);
const job = await client.submitScan("https://example.com", {
detail: "tiny"
});
console.log(job.status, job.jobId, job.scanId, job.statusUrl);
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.
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.Retry-After; the SDK uses it for polling/retry timing.completed and completed_limited.failed, expired, and rate_limited.FAQs
Official TypeScript SDK for the CertScore Pulse API.
We found that @certscore/sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Product
Create ClickUp tasks from Socket alerts, automate ticketing with custom rules, and keep alert and task status synchronized.

Product
Create and manage Asana tasks directly from Socket alerts, with manual task creation, automated ticketing rules, and two-way sync.

Security News
Open VSX has removed three extension IDs from its malicious-extension list as the legitimate publishers they impersonated move to claim the names for themselves.