BrowserShield

Public API

Look up browser vulnerabilities by User-Agent

Call this endpoint from a third-party website. It reads the visitor User-Agent automatically, or you can pass one as a parameter, and returns how many known CVEs still match that version.

Quick start

No API key. CORS is open. A frontend fetch from your site sends the visitor User-Agent header automatically.

const res = await fetch("https://ismybrowsersafe.org/api/v1/lookup");
const data = await res.json();

if (data.ok) {
  console.log(data.browser.name, data.browser.version);
  console.log(data.count); // known vulnerabilities
}

Endpoint

GET POST OPTIONS

https://ismybrowsersafe.org/api/v1/lookup

JSON responses. Cross-origin browser calls are allowed. CORS header: Access-Control-Allow-Origin: *.

How the User-Agent is chosen

  1. Request header

    If you call the API from the visitor’s browser with fetch/XHR and omit ua, the browser sends its User-Agent. source is "header".

  2. Query parameter

    Pass ua, userAgent or user_agent to inspect any string, including navigator.userAgent. source is "query".

  3. JSON body

    POST {"userAgent":"..."} or {"ua":"..."}. Useful on the server. source is "body".

Priority: JSON body > query parameter > User-Agent header.

Parameters

Name In Description
ua query / body User-Agent string. Aliases: userAgent, user_agent. Max 1024 characters.
details query / body Set to 1 or true to include a CVE list in items. Alias: include=cves.
limit query / body CVE page size when details=1. Default 20, maximum 50. Alias: page_size.
page query / body CVE page number, starting at 1.
severity query / body Filter items only: critical, high, medium, low. count still includes every severity.

Response

Successful responses always include ok: true and count. count is the number of publicly disclosed CVEs still matching the detected version.

{
  "ok": true,
  "source": "header",
  "browser": { "id": "chrome", "name": "Google Chrome", "version": "122.0.6261.94" },
  "engine": { "id": "chromium", "name": "Chromium", "version": "122.0.6261.94" },
  "os": "windows",
  "architecture": "x86_64",
  "status": "high",
  "riskScore": 72,
  "confidence": "high",
  "estimated": false,
  "majorVersionsBehind": 23,
  "count": 150,
  "vulnerabilities": { "total": 150, "critical": 3, "high": 37, "medium": 92, "low": 18 },
  "knownExploited": 2,
  "securityFixesSinceVersion": 327,
  "recommendation": {
    "action": "update",
    "message": "Update Google Chrome to the latest version. Latest stable: 145.0.0.0.",
    "messageKey": "recommend.update_chrome"
  }
}
Field Description
countNumber of known vulnerabilities still matching this version. Same as vulnerabilities.total.
vulnerabilitiesBreakdown by critical / high / medium / low.
statussafe, low, medium, high, critical, or unknown.
estimatedtrue when the version is coarse, for example a frozen Chrome User-Agent.
itemsPresent only when details=1. Each item includes cve, severity, cvss, title, fixedVersion and exploitation flags.

Errors

{ "ok": false, "error": "unrecognized user-agent" }

400 if the User-Agent is missing, too long, or unrecognized. 500 if lookup fails internally.

Examples

Frontend: current visitor

Use this on your website. The visitor User-Agent is sent by the browser. No extra headers required, so there is no CORS preflight.

async function checkVisitor() {
  const res = await fetch("https://ismybrowsersafe.org/api/v1/lookup");
  const data = await res.json();
  if (!data.ok) throw new Error(data.error);
  return data.count;
}

Frontend: pass navigator.userAgent

Equivalent to the header, but explicit. Useful if you already captured the string.

const ua = encodeURIComponent(navigator.userAgent);
const res = await fetch(
  "https://ismybrowsersafe.org/api/v1/lookup?ua=" + ua
);
const data = await res.json();
document.getElementById("risk").textContent =
  data.browser.name + " · " + data.count + " CVEs";

Include CVE details

const res = await fetch(
  "https://ismybrowsersafe.org/api/v1/lookup?details=1&limit=5"
);
const data = await res.json();
for (const item of data.items || []) {
  console.log(item.cve, item.severity, item.title);
}

curl: inspect any User-Agent

curl -G https://ismybrowsersafe.org/api/v1/lookup \
  --data-urlencode "ua=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.94 Safari/537.36"

curl -X POST https://ismybrowsersafe.org/api/v1/lookup \
  -H "Content-Type: application/json" \
  -d "{\"userAgent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:115.0) Gecko/20100101 Firefox/115.0\",\"details\":true,\"limit\":3}"

HTML widget

Drop this onto any page to show how many known issues match the visitor’s browser.

<div id="browsershield">Checking browser…</div>
<script>
(async () => {
  const el = document.getElementById("browsershield");
  try {
    const res = await fetch("https://ismybrowsersafe.org/api/v1/lookup");
    const data = await res.json();
    if (!data.ok) throw new Error(data.error);
    el.textContent = data.browser.name + " " + data.browser.version +
      " · " + data.count + " known vulnerabilities";
  } catch (err) {
    el.textContent = "Browser check unavailable";
  }
})();
</script>

Try it

Run the lookup against this browser, or paste any User-Agent.

{ }

Notes

CORS
GET from the browser is a simple request. POST with JSON sends a preflight OPTIONS request; the API answers it.
Frozen User-Agent
Chrome may freeze the patch version in User-Agent. estimated will be true and matching uses the available version. This API does not read Client Hints from third-party sites.
Privacy
The User-Agent is not stored. Usage stats are aggregated by browser, major version, engine and OS per day.
What this is not
BrowserShield never exploits vulnerabilities. Results come from public CVE and vendor advisory data.

Check my browser