Skip to main content

Bookmark & Link Health Checker

Test and verify URLs in bulk to detect broken links (404), redirect loops, server errors (500), and latency bottlenecks.

๐Ÿ“‚
Drop your bookmark file here
or click to browse ยท Chrome / Firefox / Safari HTML export
How to export bookmarks from your browser
  • Chrome: Bookmarks menu โ†’ Bookmark manager โ†’ โ‹ฎ โ†’ Export bookmarks
  • Firefox: Bookmarks โ†’ Manage Bookmarks โ†’ Import and Backup โ†’ Export Bookmarks to HTML
  • Safari: File โ†’ Export โ†’ Bookmarksโ€ฆ
  • Edge: Settings โ†’ Favorites โ†’ โ‹ฎ โ†’ Export favorites

Verifying dozens or hundreds of URLs simultaneously presents two critical architectural challenges: browser-level Cross-Origin Resource Sharing (CORS) blocks direct browser-to-server requests, while naive server-side scrapers risk bandwidth exhaustion and Server-Side Request Forgery (SSRF) vulnerabilities.

The Bookmark Health Checker uses a hardened serverless endpoint (/api/checkBookmarkLinks) designed for low-latency batch verification.


1. SSRF Guardrails & Private Network Filteringโ€‹

To prevent the scraper from being weaponized to probe internal infrastructure or cloud metadata endpoints (169.254.169.254), incoming hostnames are validated against strict regex blocklists before network requests are initiated:

// api/checkBookmarkLinks.js (SSRF Guard)
const PRIVATE_HOST_PATTERNS = [
/^localhost$/i,
/^127\.\d+\.\d+\.\d+$/,
/^10\.\d+\.\d+\.\d+$/,
/^172\.(1[6-9]|2\d|3[01])\.\d+\.\d+$/,
/^192\.168\.\d+\.\d+$/,
/^\[?::1\]?$/,
/^0\.0\.0\.0$/,
/^169\.254\.\d+\.\d+$/, // AWS / GCP metadata service
];

function isPrivateHost(hostname) {
return PRIVATE_HOST_PATTERNS.some((pattern) => pattern.test(hostname));
}

2. Stream Aborting & Zero-Payload Body Cancellationโ€‹

Downloading entire HTML pages, multimedia streams, or large binary files across dozens of URLs would rapidly exhaust serverless execution budgets.

The architecture solves this by issuing requests with early stream cancellation:

async function fetchWithTimeout(url, method, timeoutMs) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
const startTime = Date.now();

try {
const response = await fetch(url, {
method,
signal: controller.signal,
redirect: 'follow',
headers: {
'User-Agent': 'Mozilla/5.0 (compatible; BookmarkChecker/1.0)',
'Accept': 'text/html,*/*'
}
});
clearTimeout(timeoutId);

// Cancel body download immediately โ€” only HTTP headers & status are required
if (response.body) {
response.body.cancel().catch(() => {});
}

return {
status: response.status,
statusText: response.statusText,
finalUrl: response.url,
responseTimeMs: Date.now() - startTime
};
} catch (err) {
clearTimeout(timeoutId);
throw Object.assign(err, { responseTimeMs: Date.now() - startTime });
}
}

3. HTTP Status Codes Diagnosis Tableโ€‹

Status CodeClassificationRoot Cause & Resolution
200 OKHealthyTarget URL is fully functional and serving content.
301 / 308Permanent RedirectTarget has moved permanently. Update your bookmarks/links to finalUrl.
302 / 307Temporary RedirectTemporary routing or authentication gateway.
400 Bad RequestClient ErrorMalformed URL syntax or rejected query parameters.
403 ForbiddenAccess DeniedCloudflare/WAF block, hotlink protection, or authentication wall.
404 Not FoundDead LinkResource deleted or moved without redirect. Prune from links list.
410 GoneIntentionally PurgedServer owner permanently removed the resource.
500 Internal ErrorServer FaultTarget web application crashed during request processing.
502 Bad GatewayProxy ErrorReverse proxy or load balancer failed to reach upstream origin.
503 UnavailableMaintenance / OverloadTarget server temporarily capacity-constrained or undergoing maintenance.

4. Client-Side Security & Zero-Persistence Guaranteeโ€‹

  • No Link Storage: URLs submitted for checking are processed in volatile RAM buffers and immediately returned to your browser.
  • No Telemetry Tracking: The tool does not store URLs in databases or analytics platforms.
  • Isolated Execution: Each batch of URLs executes inside an isolated Vercel serverless sandbox.

Get notified about updates to this tool

No spam. Just high-quality updates about new features and guides.