Understanding HTTP Network Error Logging (NEL)
Network reliability is crucial for modern web applications, but understanding when and why network requests fail can be challenging. HTTP Network Error Logging (NEL) is a W3C specification that enables websites to collect information about failed network requests from real users, providing insights into connectivity issues that might otherwise go unnoticed.
What is Network Error Logging?
Network Error Logging (NEL) is a mechanism that allows web servers to instruct browsers to collect and report network-level errors. Unlike traditional application monitoring that only tracks requests that reach your server, NEL captures failures that occur before the request even completes - such as DNS failures, connection timeouts, TLS handshake errors, and other network-level issues.
When a browser encounters these types of errors, it can automatically send a report to a specified endpoint, giving you visibility into problems that users experience but might never report manually.
How NEL Works
The NEL mechanism involves two key HTTP response headers that work together:
1. The NEL Header
The NEL header instructs the browser to monitor network requests and defines the reporting policy:
NEL: {"report_to":"nel-endpoint","max_age":604800,"success_fraction":0.01,"failure_fraction":1.0}
Complete NEL Parameters
report_to (required): String that references a reporting group defined in the Report-To header. This links the NEL policy to the endpoint where reports should be sent. The value must match the
groupfield in a Report-To header.Example:
"report_to":"nel-endpoint"max_age (required): Integer specifying how long (in seconds) the browser should remember and apply this NEL policy. Once this time expires, the browser stops collecting reports until it receives a new NEL header. Common values include:
86400(1 day)604800(7 days)2592000(30 days)
Setting
max_ageto0immediately disables NEL reporting for the origin.success_fraction (optional, default: 0.0): Decimal value between 0.0 and 1.0 that specifies the sampling rate for successful network requests. Due to the high volume of successful requests, this is typically set very low or to 0.
0.0= Report no successful requests (recommended for most cases)0.01= Report 1% of successful requests1.0= Report all successful requests (only for debugging/testing)
failure_fraction (optional, default: 1.0): Decimal value between 0.0 and 1.0 that specifies the sampling rate for failed network requests. Since failures are typically less common than successes, this is often set to 1.0 to capture all failures.
1.0= Report all failures (recommended)0.5= Report 50% of failures0.0= Report no failures
include_subdomains (optional, default: false): Boolean that determines whether the NEL policy applies to all subdomains of the origin. When set to
true, the policy covers the origin and all its subdomains.Example with subdomains enabled:
NEL: {"report_to":"nel","max_age":604800,"include_subdomains":true}If set on
https://example.com, this policy would also apply to:https://www.example.comhttps://api.example.comhttps://cdn.example.com
Important: Only use
include_subdomainsif you control all subdomains and have configured appropriate Report-To headers for each.request_headers (optional): Array of HTTP request header names that should be included in NEL reports. This allows you to capture specific headers that might be relevant for debugging network failures.
Example:
NEL: {"report_to":"nel","max_age":604800,"request_headers":["User-Agent","Referer"]}Privacy note: Only request headers explicitly listed will be included. Sensitive headers like cookies or authorization are excluded by the browser regardless of configuration.
response_headers (optional): Array of HTTP response header names that should be included in NEL reports when available. Useful for capturing server-provided debugging information.
Example:
NEL: {"report_to":"nel","max_age":604800,"response_headers":["X-Request-ID","X-Cache-Status"]}These headers are only included if the request progressed far enough to receive a response. For DNS or connection failures, no response headers will be present.
Complete Example with All Parameters
NEL: {
"report_to": "network-errors",
"max_age": 2592000,
"success_fraction": 0.0,
"failure_fraction": 1.0,
"include_subdomains": true,
"request_headers": ["User-Agent"],
"response_headers": ["X-Request-ID", "X-Cache-Status"]
}
This configuration:
- Reports all failures, no successes
- Valid for 30 days
- Applies to all subdomains
- Includes User-Agent from requests and X-Request-ID, X-Cache-Status from responses
2. The Report-To Header
The Report-To header defines where reports should be sent:
Report-To: {"group":"nel-endpoint","max_age":604800,"endpoints":[{"url":"https://collector.example.com/reports"}]}
Key parameters:
- group: A name for this reporting endpoint group
- max_age: How long the browser should cache this configuration
- endpoints: Array of URLs where reports should be sent
Types of Errors Captured
NEL can capture various network-level failures:
DNS Resolution Errors
- DNS name resolution failures
- DNS timeout errors
- No DNS response
Connection Errors
- Connection refused
- Connection timeout
- Connection reset
- Network unreachable
TLS/SSL Errors
- Certificate validation failures
- TLS handshake timeouts
- Protocol version mismatches
- Cipher suite negotiation failures
HTTP Protocol Errors
- HTTP protocol errors
- Response abandoned (connection closed before complete)
- Incomplete responses
Report Structure
When a network error occurs, the browser sends a JSON report to the specified endpoint:
{
"age": 142,
"type": "network-error",
"url": "https://example.com/api/data",
"body": {
"elapsed_time": 5000,
"method": "GET",
"phase": "connection",
"protocol": "http/1.1",
"referrer": "https://example.com/",
"sampling_fraction": 1.0,
"server_ip": "203.0.113.42",
"status_code": 0,
"type": "tcp.refused"
}
}
Report Fields Description
| Field | Location | Description |
|---|---|---|
| age | Top-level | The number of milliseconds between the report being generated and its transmission to the collector. Helps understand delays in report delivery. |
| type | Top-level | Always set to "network-error" for NEL reports. Distinguishes NEL reports from other Reporting API types (CSP violations, deprecation warnings, etc.). |
| url | Top-level | The full URL that experienced the network error. The address the browser was attempting to reach when the failure occurred. |
| elapsed_time | Body | Time in milliseconds from request initiation until error occurrence. For DNS failures, represents DNS lookup time. For connection failures, includes DNS time plus connection attempt time. Identifies whether failures are quick (immediate rejection) or slow (timeouts). |
| method | Body | The HTTP method used for the request (GET, POST, PUT, DELETE, etc.). Useful for understanding if certain request types are more prone to failures. |
| phase | Body | Stage where the request failed: dns (DNS resolution), connection (TCP connection establishment), or application (after connection established during HTTP exchange). Crucial for diagnosing where in the network stack problems occur. |
| protocol | Body | Network protocol being used: http/1.1, h2 (HTTP/2), or h3 (HTTP/3). Helps identify protocol-specific issues. |
| referrer | Body | URL of the page that initiated the request. Provides context about where users were when encountering the error and helps trace navigation paths leading to failures. |
| sampling_fraction | Body | Sampling rate in effect when this report was generated (0.0 to 1.0). If failure_fraction is 0.5, this shows 0.5, meaning only 50% of failures are reported. Essential for accurately extrapolating total failure counts. |
| server_ip | Body | IP address the browser attempted to connect to. Only present if DNS resolution succeeded. Invaluable for identifying issues with specific server IPs, such as when one server in a pool is malfunctioning or unreachable. |
| status_code | Body | HTTP status code returned by the server if the request progressed far enough to receive one. For most network errors (connection refused, DNS failures), this is 0 because no HTTP response was received. Non-zero values indicate connection succeeded but HTTP layer encountered an issue. |
| type | Body | Specific error type. Common values: dns.name_not_resolved, dns.timed_out, tcp.refused, tcp.timed_out, tcp.closed, tcp.reset, tcp.aborted, tls.cert.name_invalid, tls.cert.date_invalid, http.protocol.error, http.response.invalid, abandoned. Understanding error types helps prioritize fixes and identify failure patterns. |
Use Cases
Network Error Logging provides visibility into failures that traditional monitoring systems miss. Here are the primary scenarios where NEL proves invaluable:
Regional and Geographic Issues: NEL reports can reveal if users in specific geographic regions experience connectivity problems due to ISP routing issues, regional network outages, or CDN edge node failures. By analyzing the distribution of errors across different locations, you can identify regional infrastructure problems before they escalate.
DNS Resolution Problems: DNS failures often go unnoticed by server-side monitoring since the request never reaches your infrastructure. NEL captures these DNS errors, allowing you to detect DNS provider outages, misconfigured records, or DNS poisoning attempts early. You’ll see increased dns.name_not_resolved or dns.timed_out errors before the issue affects a significant portion of your user base.
Certificate and TLS Issues: Certificate problems like expired certificates, invalid certificate chains, or hostname mismatches are immediately visible through NEL reports. This is particularly useful for detecting certificate renewal failures or CDN configuration issues that might only affect specific edge locations. You can also identify client-side problems like incorrect system clocks that cause certificate validation failures.
Infrastructure Performance: NEL helps identify connection timeouts, refused connections, and server overload issues across your infrastructure. If certain servers or load balancers start refusing connections or timing out, NEL reports will show patterns in the server_ip field, helping you pinpoint problematic hosts even when they’re behind load balancers or CDNs.
Attack Detection and Mitigation: Unusual patterns in network error reports can indicate ongoing DDoS attacks, network-level attacks, or infrastructure issues. A sudden spike in connection refused errors might indicate rate limiting or firewall changes, while patterns of TLS errors could suggest man-in-the-middle attack attempts.
Privacy Considerations
NEL is designed with privacy in mind:
- Reports are sent without credentials (no cookies or authentication headers)
- The browser can apply its own sampling rate on top of the server’s configuration
- Users can disable NEL through browser settings or extensions
- Reports are batched and sent asynchronously to minimize performance impact
Browser Support
NEL is supported by modern browsers:
- Chrome/Edge: Full support (Chromium 69+)
- Firefox: Not yet implemented (as of 2025)
- Safari: Not yet implemented
- Opera: Full support (Chromium-based)
Despite limited browser support, NEL can still provide valuable insights from the significant portion of users on Chromium-based browsers.
Example Configurations
Basic Configuration
A minimal setup for production websites:
NEL: {"report_to":"network-errors","max_age":604800,"success_fraction":0,"failure_fraction":1.0}
Report-To: {"group":"network-errors","max_age":604800,"endpoints":[{"url":"https://reports.example.com/nel"}]}
This configuration:
- Reports all network failures (
failure_fraction=1.0) - Does not report successful requests (
success_fraction=0) - Maintains the policy for 7 days (
max_age=604800) - Sends reports to a dedicated collection endpoint
Configuration with Subdomains
For organizations managing multiple subdomains:
NEL: {"report_to":"nel","max_age":2592000,"failure_fraction":1.0,"include_subdomains":true}
Report-To: {"group":"nel","max_age":2592000,"endpoints":[{"url":"https://collector.example.com/nel"}]}
This applies the NEL policy to all subdomains for 30 days.
Advanced Configuration with Headers
For detailed debugging with request and response headers:
NEL: {
"report_to":"nel-debug",
"max_age":604800,
"success_fraction":0,
"failure_fraction":1.0,
"request_headers":["User-Agent","Referer"],
"response_headers":["X-Request-ID","X-Cache-Status","X-Served-By"]
}
Report-To: {
"group":"nel-debug",
"max_age":604800,
"endpoints":[{"url":"https://reports.example.com/nel/debug"}]
}
This configuration includes specific headers in reports to aid in troubleshooting.
Testing Configuration
For initial testing with sampling:
NEL: {"report_to":"nel-test","max_age":86400,"success_fraction":0.01,"failure_fraction":0.1}
Report-To: {"group":"nel-test","max_age":86400,"endpoints":[{"url":"https://test-collector.example.com/nel"}]}
This configuration:
- Reports 1% of successful requests and 10% of failures
- Short 1-day policy for quick iterations
- Uses a test endpoint to avoid mixing with production data
Conclusion
HTTP Network Error Logging provides powerful visibility into network-level failures that affect your users but often go undetected by application monitoring. By implementing NEL, you can proactively identify and resolve connectivity issues, improve service reliability, and better understand the real-world network conditions your users experience.
While browser support is currently limited to Chromium-based browsers, the insights from this significant user segment can be invaluable for maintaining a reliable web service. As the specification matures and gains broader adoption, NEL will become an essential tool in every web operations toolkit.