Skip to content

Privacy Score — PHP 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 PHP implementation — the same logic the interactive tool runs, in a shareable, citable form.

<?php
// privacy-score — composite privacy scoring engine.
//
// Language: PHP (8.x, 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.

declare(strict_types=1);

/** Round to the nearest point and pin into the 0..25 window. */
function clamp25(float $points): int
{
    return (int) max(0, min(25, round($points)));
}

function statusFor(int $points): string
{
    return $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(int $signalCount, int $highRisk, int $mediumRisk): int
{
    $surface = max(0, $signalCount - 12) * 0.5;
    return clamp25(25 - $highRisk * 4 - $mediumRisk * 1.5 - $surface);
}

function passwordPoints(int $score, bool $breached): int
{
    $base = max(0, 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(array $grades): int
{
    if (in_array('F', $grades, true)) return 0;
    if (in_array('C', $grades, true)) return 10;
    if (in_array('B', $grades, true)) return 18;
    return count($grades) > 0 ? 25 : 0;
}

function breachPoints(bool $pwned): int { return $pwned ? 0 : 25; }

function letterFor(int $percent, int $max): string
{
    return $max === 0 ? '—' : ($percent >= 85 ? 'A' : ($percent >= 70 ? 'B' : ($percent >= 50 ? 'C' : 'D')));
}

// Renormalize over the checks that ran and grade the overall letter.
function scorePrivacy(array $points): array
{
    $total = array_sum($points);
    $max = count($points) * 25;
    $percent = $max === 0 ? 0 : (int) round($total / $max * 100);
    return [
        'total' => $total,
        'max' => $max,
        'percent' => $percent,
        'letter' => letterFor($percent, $max),
        'statuses' => array_map('statusFor', $points),
    ];
}

$checks = [
    fingerprintPoints(18, 2, 4),     // 8
    passwordPoints(4, true),         // 8 (breach floor)
    headersPoints(['A', 'A', 'B']),  // 18
    breachPoints(false),             // 25
];
print_r($checks);
print_r(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 →