Network Errors (NEL)
Configure Network Error Logging to detect connection failures that are invisible to your server logs — DNS resolution failures, TCP timeouts, TLS handshake errors, and more.
New to network error monitoring? Read our Network Errors overview to understand the benefits before diving into configuration.
What is Network Error Logging?
Network Error Logging (NEL) is a W3C standard that enables browsers to automatically report network failures to an endpoint you specify. When a user experiences a DNS resolution failure, TCP timeout, or TLS handshake error, their browser captures the details and sends a report — even though the request never reached your servers.
Unlike traditional server-side monitoring, NEL captures failures that happen before requests reach your infrastructure. This "last mile" visibility is critical because server logs are completely blind to these connection-phase errors.
NEL uses two HTTP headers: Report-To defines where to send reports, and NEL enables the
feature with configuration options like sampling rates. Once configured, browsers automatically collect and report
network errors — no JavaScript SDK required.
Specification
- W3C Network Error Logging — Official specification
- MDN: Network Error Logging — Developer documentation
Browser Support
NEL has ~80% global browser support, covering Chromium-based browsers.
| Browser | NEL Support | Notes |
|---|---|---|
| Chrome | 71+ | Full support |
| Edge | 79+ | Full support |
| Opera | 58+ | Full support |
| Samsung Internet | 10.2+ | Full support |
| Firefox | — | Not supported |
| Safari | — | Not supported |
Why Monitor Network Errors?
Network errors reveal connectivity issues that are completely invisible to server-side monitoring:
- Detect regional outages — Identify ISP routing issues, BGP misconfigurations, and regional DNS problems affecting specific user populations
- Catch DNS hijacking — Detect when DNS responses are tampered with or when your domain fails to resolve
- Monitor TLS health — Get alerts about certificate expiration, cipher mismatches, and handshake failures
- Diagnose connectivity — Understand TCP-level failures like timeouts, resets, and refused connections
- Build SLA evidence — Collect timestamped proof of third-party network failures for vendor escalation
Who Benefits
- SRE teams — Gain visibility into network-layer failures that traditional APM tools miss
- Network engineers — Diagnose routing issues and CDN edge failures with real user data
- Operations teams — Detect regional outages before support tickets arrive
When to Enable
NEL is recommended for all production websites. It provides critical visibility into the "last mile" of network connectivity that server-side monitoring cannot see. Since NEL doesn't have a report-only mode, use sampling rates to control report volume during initial deployment.
How to Configure
Report-To header. The modern Reporting-Endpoints header does not
yet support NEL. See the
Chrome Reporting API migration guide
for details.
Step 1: Set Up the Report-To Header
First, define where browsers should send NEL reports using the Report-To header:
Report-To: {"group":"default","max_age":86400,"endpoints":[{"url":"https://reporting-api.app/browser-reports/YOUR-ENDPOINT-UUID"}]}
Replace YOUR-ENDPOINT-UUID with your application's unique endpoint from the
reporting-api.app dashboard.
Header fields:
group— Name of the endpoint group (referenced by the NEL header)max_age— How long (in seconds) the browser remembers this configurationendpoints— Array of URLs to receive reports
Step 2: Configure the NEL Header
Next, enable Network Error Logging by adding the NEL header:
NEL: {"report_to":"default","max_age":86400}
This minimal configuration reports all network failures to the default endpoint group.
Step 3: Set Sampling Rates
NEL doesn't have a report-only mode. Instead, use sampling rates to control report volume:
NEL: {"report_to":"default","max_age":86400,"failure_fraction":1.0,"success_fraction":0.01}
Sampling options:
failure_fraction— Proportion of failed requests to report (0.0-1.0, default: 1.0)success_fraction— Proportion of successful requests to report (0.0-1.0, default: 0.0)
Recommended settings:
-
Start with:
"failure_fraction": 1.0(report all failures) and"success_fraction": 0(no success reports) -
High-traffic sites: Reduce
failure_fractionto 0.1 or 0.5 if report volume is too high -
Performance monitoring: Set
"success_fraction": 0.01to sample 1% of successful requests for latency data
Step 4: Monitor Reports
After deploying the headers, NEL reports will start flowing automatically. Monitor incoming reports in your dashboard for patterns like:
- DNS failures from specific regions — May indicate ISP or regional DNS issues
- TCP timeouts clustering by ASN — Could signal routing problems
- TLS certificate errors — Check for expiring or misconfigured certificates
Step 5: Set Up Integrations
Route NEL reports to your existing tools for alerting and analysis:
- AppSignal integration — Track network errors alongside application errors
- Webhook integration — Send reports to Slack, PagerDuty, or custom endpoints
- Google Chat integration — Post alerts to team chat spaces
See the Integrations documentation for setup instructions.
Understanding NEL Reports
When a network error occurs, the browser sends a JSON report to your endpoint. Understanding this payload helps you diagnose connectivity issues.
Report Fields
| Field | Description |
|---|---|
type |
Error type (e.g., dns.name_not_resolved, tcp.timed_out)
|
phase |
Network phase where the error occurred (dns, connection, application)
|
elapsed_time |
Milliseconds from request start to failure |
server_ip |
IP address of the server (empty if DNS failed) |
protocol |
Protocol used (http/1.1, h2, h3) |
method |
HTTP method (GET, POST, etc.) |
status_code |
HTTP status code (0 if connection failed before response) |
sampling_fraction |
The sampling rate applied to this report |
referrer |
Referrer of the request |
Example Report
{
"type": "network-error",
"age": 20,
"url": "https://example.com/api/data",
"body": {
"type": "dns.name_not_resolved",
"phase": "dns",
"elapsed_time": 18,
"method": "GET",
"protocol": "http/1.1",
"referrer": "https://example.com/dashboard",
"sampling_fraction": 1,
"server_ip": "",
"status_code": 0
}
}
Error Types Reference
NEL categorizes errors by the network phase where they occur. Here are the common error types:
DNS Errors
| Type | Description |
|---|---|
dns.unreachable |
User's DNS server is unreachable |
dns.name_not_resolved |
DNS server couldn't resolve the hostname |
dns.failed |
DNS request failed (e.g., SERVFAIL) |
dns.address_changed |
Server IP changed (security measure) |
TCP Errors
| Type | Description |
|---|---|
tcp.timed_out |
TCP connection timed out |
tcp.closed |
TCP connection closed by server |
tcp.reset |
TCP connection reset |
tcp.refused |
TCP connection refused |
tcp.aborted |
TCP connection aborted |
tcp.address_invalid |
Invalid IP address |
tcp.address_unreachable |
IP address unreachable |
TLS Errors
| Type | Description |
|---|---|
tls.version_or_cipher_mismatch |
TLS version or cipher not supported |
tls.cert.date_invalid |
Certificate expired or not yet valid |
tls.cert.name_invalid |
Certificate hostname mismatch |
tls.cert.revoked |
Certificate has been revoked |
tls.protocol.error |
TLS protocol error |
HTTP Errors
| Type | Description |
|---|---|
http.error |
HTTP 4xx or 5xx response received |
http.protocol.error |
HTTP protocol error |
http.response.invalid |
Invalid HTTP response (empty, content-length mismatch) |
http.response.redirect_loop |
Redirect loop detected |
Server Configuration Examples
Nginx
server {
# ... your existing configuration ...
# Report-To header for NEL (required - Reporting-Endpoints not yet supported for NEL)
add_header Report-To '{"group":"default","max_age":86400,"endpoints":[{"url":"https://reporting-api.app/browser-reports/YOUR-UUID"}]}' always;
# NEL header
add_header NEL '{"report_to":"default","max_age":86400,"failure_fraction":1.0}' always;
}
Ruby on Rails
# Add Report-To and NEL headers (NEL requires Report-To, not Reporting-Endpoints)
config.action_dispatch.default_headers.merge!(
"Report-To" => '{"group":"default","max_age":86400,"endpoints":[{"url":"https://reporting-api.app/browser-reports/YOUR-UUID"}]}',
"NEL" => '{"report_to":"default","max_age":86400,"failure_fraction":1.0}'
)
Apache
Header always set Report-To '{"group":"default","max_age":86400,"endpoints":[{"url":"https://reporting-api.app/browser-reports/YOUR-UUID"}]}'
Header always set NEL '{"report_to":"default","max_age":86400,"failure_fraction":1.0}'
Troubleshooting
Reports Not Appearing
- Check browser support — NEL only works in Chromium-based browsers (Chrome, Edge, Opera). Firefox and Safari do not support NEL.
-
Verify headers are sent — Use browser DevTools (Network tab) to confirm both
Report-ToandNELheaders are present in responses. - Check allowed origins — Ensure your website's origin is whitelisted in your application settings.
- Wait for batching — Browsers may batch reports before sending. Be patient after triggering a test.
Too Many Reports
-
Reduce failure_fraction — Set
"failure_fraction": 0.1to report only 10% of failures. -
Disable success reporting — Ensure
"success_fraction": 0unless you need latency data. - Check for infrastructure issues — High report volume may indicate real network problems worth investigating.
Debugging Locally
-
Chrome internals — Visit
chrome://net-export/to capture network logs including NEL policy registration. -
View cached policies — Check
chrome://net-internals/#reportingto see registered NEL policies and pending reports. - Note: Report delivery does not appear in Chrome DevTools Network tab.
Next Steps
- Deprecations — Monitor deprecated API usage
- Integrations — Route reports to your observability tools
- Getting Started — Set up your first application