Monitoring Image 404s with Sentry and Log Pipelines
Set up image 404 monitoring using Sentry breadcrumbs, custom error events, and log pipeline aggregation to detect broken images before users report them.
Broken images are silent failures. Users see a broken-image icon and move on without filing a support ticket. Without image 404 monitoring, teams only learn about broken images when SEO rankings drop or when a customer explicitly complains. Instrumenting your frontend to capture image load errors and route them through Sentry or a log pipeline gives you visibility before the impact accumulates.
This guide covers capturing img error events in JavaScript, sending them to Sentry as custom breadcrumbs and events, aggregating them in a log pipeline, and setting up alerts when image 404 rates exceed a threshold.
Detection
Capturing image load errors in the browser
The browser fires an error event on every img element that fails to load. Registering a document-level listener in capture phase catches all failures regardless of when img elements are inserted into the DOM — including those from React renders, virtual scroll lists, and third-party widgets.
Collect the failing URL, the page URL where it occurred, the img alt text, and the timestamp. This gives your monitoring system enough context to group errors by image domain, route, and time window.
// monitoring/imageErrors.ts
interface ImageErrorEvent {
imageUrl: string;
pageUrl: string;
alt: string;
timestamp: number;
}
export function initImageErrorMonitoring() {
document.addEventListener(
'error',
(event) => {
const target = event.target as HTMLElement;
if (target.tagName !== 'IMG') return;
const img = target as HTMLImageElement;
const payload: ImageErrorEvent = {
imageUrl: img.currentSrc || img.src,
pageUrl: window.location.href,
alt: img.alt ?? '',
timestamp: Date.now(),
};
// Skip placeholder.pics fallback failures
if (payload.imageUrl.includes('fallback.pics')) return;
reportImageError(payload);
},
true // capture phase
);
} Sentry
Sending image errors to Sentry as custom events
Sentry.captureEvent() sends a fully structured event with fingerprinting, context, and tags. Use it for image 404s so they appear as grouped issues in the Sentry issues list, separate from JavaScript exceptions.
Set the fingerprint to the image URL hostname so all 404s from the same CDN domain group into one issue. This prevents noise from high-frequency identical errors filling your issues list.
import * as Sentry from '@sentry/browser';
function reportImageError(payload: ImageErrorEvent) {
const url = new URL(payload.imageUrl);
Sentry.captureEvent({
message: `Image 404: ${payload.imageUrl}`,
level: 'warning',
fingerprint: ['image-404', url.hostname],
tags: {
image_host: url.hostname,
page_path: new URL(payload.pageUrl).pathname,
},
extra: {
imageUrl: payload.imageUrl,
alt: payload.alt,
pageUrl: payload.pageUrl,
},
timestamp: payload.timestamp / 1000,
});
// Also add as breadcrumb for session context
Sentry.addBreadcrumb({
category: 'image.error',
message: payload.imageUrl,
level: 'warning',
data: { alt: payload.alt },
});
} Log pipeline
Aggregating image errors in a log pipeline
For high-traffic sites, sending every image 404 to Sentry can exhaust your event quota. Route image errors to a log pipeline instead — Datadog, Grafana Loki, or CloudFlare Logpush — and aggregate counts by image URL and time window.
Batch events locally in a small in-memory queue and flush every 30 seconds or when the queue reaches 20 events. This reduces the number of requests from the frontend without losing individual error events.
// Batched log pipeline approach
const errorQueue: ImageErrorEvent[] = [];
let flushTimer: ReturnType<typeof setTimeout> | null = null;
function enqueue(error: ImageErrorEvent) {
errorQueue.push(error);
if (errorQueue.length >= 20) flush();
else if (!flushTimer) {
flushTimer = setTimeout(flush, 30_000);
}
}
async function flush() {
if (flushTimer) { clearTimeout(flushTimer); flushTimer = null; }
if (!errorQueue.length) return;
const batch = errorQueue.splice(0);
await fetch('/api/log/image-errors', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ events: batch }),
keepalive: true,
});
} Alerting
Setting up alerts when image 404 rate spikes
A sudden spike in image 404s from a single domain indicates a CDN misconfiguration or accidental deletion. Configure an alert that fires when more than 50 unique image URLs return 404 within a 10-minute window from the same hostname.
In Sentry, use Alert Rules with a count threshold on events tagged image_host. In Datadog, use a metric monitor on the image error log count grouped by image_host.
Fallback integration
Pairing monitoring with fallback.pics for graceful degradation
The onerror fallback and the monitoring instrumentation work together. The onerror handler fixes the visual experience for the user immediately; the monitoring layer records the failure for your engineering team to fix the root cause.
Skip reporting errors for fallback.pics URLs (as shown in the detection code above). The fallback is working as designed — no need to monitor a URL that intentionally never 404s.
// Complete integration: fallback + monitoring
document.addEventListener('error', (event) => {
const target = event.target as HTMLElement;
if (target.tagName !== 'IMG') return;
const img = target as HTMLImageElement;
const failedUrl = img.currentSrc || img.src;
// Skip if already a fallback URL
if (failedUrl.includes('fallback.pics')) return;
// Apply fallback
if (!img.dataset['fallbackApplied']) {
img.dataset['fallbackApplied'] = '1';
img.src = `https://fallback.pics/api/v1/${img.width || 400}x${img.height || 300}/7C3AED/FFFFFF?text=Unavailable`;
}
// Report to monitoring
reportImageError({ imageUrl: failedUrl, pageUrl: location.href, alt: img.alt, timestamp: Date.now() });
}, true); Resources
Monitoring guides and fallback.pics reference
Combine proactive scanning with runtime monitoring for full coverage of broken image scenarios.
https://fallback.pics/docs/
https://fallback.pics/placeholder-image-api/
https://fallback.pics/blog/automated-broken-image-scanner/
https://fallback.pics/blog/lighthouse-ci-missing-image-cls/ Key takeaways
What to standardize before shipping
- Register a document-level error listener in capture phase to catch all image load failures, including those from dynamically rendered components and third-party widgets.
- Send image 404s to Sentry as custom captureEvent() calls with fingerprinting by CDN hostname so each domain's issues group separately.
- For high-traffic sites, batch errors into a local queue and flush every 30 seconds to avoid overwhelming your Sentry event quota or log pipeline ingestion.
- Alert on spikes in image 404 rate per domain (50+ unique URLs in 10 minutes) to catch CDN misconfigurations before they accumulate into an SEO or UX problem.
- Skip reporting errors from fallback.pics URLs — the fallback is working as designed and does not need monitoring.
Production fallback layer
Use fallback.pics anywhere an image URL is accepted.
Start with one deterministic URL and standardize fallback behavior across your design system.