Skip to content

Privacy Score — JavaScript source

One number for your privacy health: your browser fingerprint, a test password's strength and breach exposure, and a site's security headers — four checks, one score, concrete fixes. Runs in your browser; only a 5-character hash prefix ever leaves it.

This is the JavaScript implementation — the same logic the interactive tool runs, in a shareable, citable form.

// privacy-score — composite privacy scoring engine.
//
// Language: JavaScript (ES2020, no dependencies)
// Source:   CosmoDev polyglot showcase port of the Privacy Score tool,
//           ported from src/lib/privacy-score.ts (canonical TypeScript).
// License:  display source — part of CosmoDev's polyglot tool pages.
//
// Four category checks, each scored out of 25; the overall percent is
// renormalized over the categories that actually ran — skipping a check
// never lowers your score. Letter bands: >=85 A, >=70 B, >=50 C, else D.

const clamp25 = (points) => Math.max(0, Math.min(25, Math.round(points)));

const statusFor = (points) => (points >= 20 ? 'ok' : points >= 10 ? 'warn' : 'bad');

// More distinguishable signals make a browser more unique: high-risk
// signals cost 4 each, medium 1.5, and a large surface costs a little more.
function fingerprintPoints(signalCount, highRiskCount, mediumRiskCount) {
  const surface = Math.max(0, signalCount - 12) * 0.5;
  return clamp25(25 - highRiskCount * 4 - mediumRiskCount * 1.5 - surface);
}

function passwordPoints(score, breached) {
  const base = (Math.max(0, Math.min(4, score)) / 4) * 25;
  // Breached is urgent regardless of strength: x0.32 floors even a
  // score-4 password at 8 points -> 'bad' -> the change-it recommendation.
  return clamp25(breached ? base * 0.32 : base);
}

function headersPoints(grades) {
  const counts = { A: 0, B: 0, C: 0, F: 0 };
  for (const g of grades) if (g in counts) counts[g]++;
  if (counts.F > 0) return 0;
  if (counts.C > 0) return 10;
  if (counts.B > 0) return 18;
  return grades.length > 0 ? 25 : 0;
}

const breachPoints = (pwned) => (pwned ? 0 : 25);

function letterFor(percent, max) {
  if (max === 0) return '—';
  if (percent >= 85) return 'A';
  if (percent >= 70) return 'B';
  if (percent >= 50) return 'C';
  return 'D';
}

// Renormalize over the checks that ran and grade the overall letter.
function scorePrivacy(points) {
  const total = points.reduce((a, p) => a + p, 0);
  const max = points.length * 25;
  const percent = max === 0 ? 0 : Math.round((total / max) * 100);
  return {
    total,
    max,
    percent,
    letter: letterFor(percent, max),
    statuses: points.map(statusFor),
  };
}

const checks = [
  fingerprintPoints(18, 2, 4),    // 8
  passwordPoints(4, true),        // 8 (breach floor)
  headersPoints(['A', 'A', 'B']), // 18
  breachPoints(false),            // 25
];
console.log(checks);
console.log(scorePrivacy(checks));

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →