Resource Timing API: Measuring DNS, TCP, and TLS
The Resource Timing API enables web developers to collect granular, high-resolution network timing data for every resource fetched by a web page. By exposing specific timestamps for each step of the network lifecycle, this API allows engineers to isolate and measure individual connection setup phases, specifically Domain Name System (DNS) lookups, Transmission Control Protocol (TCP) handshakes, and Transport Layer Security (TLS) negotiations. Understanding how these metrics are captured and calculated is essential for identifying infrastructure bottlenecks and optimizing modern web performance.
Accessing Resource Timing Data
The Resource Timing API is accessible via the global
performance object in modern browsers. Fetching resource
performance records is typically done using:
const resources = performance.getEntriesByType('resource');Each item returned is a PerformanceResourceTiming
object, which inherits from PerformanceEntry. These objects
contain timestamps recorded with microsecond precision
(DOMHighResTimeStamp), representing milliseconds elapsed
since the time origin (typically page navigation start).
Isolating the DNS Phase
Before a client can connect to an origin server, it must resolve the domain name into an IP address. The Resource Timing API captures this operation using two properties:
domainLookupStart: The timestamp immediately before the browser starts the domain name lookup.domainLookupEnd: The timestamp immediately after the domain name lookup is complete.
To calculate the total DNS lookup duration:
const dnsDuration = resource.domainLookupEnd - resource.domainLookupStart;If a persistent connection is reused or the domain is already cached
by the browser, both values will often be identical to
fetchStart, resulting in a duration of zero.
Isolating the TCP Handshake
Once the IP address is resolved, the browser establishes a TCP connection to the host. The connection phase is tracked by:
connectStart: The timestamp immediately before the browser starts establishing the connection to the server.connectEnd: The timestamp immediately after the connection is established, including the completion of the TLS handshake (if HTTPS is used).
For unencrypted HTTP connections, the TCP handshake duration is calculated directly as:
const tcpDuration = resource.connectEnd - resource.connectStart;Isolating the TLS Negotiation Phase
When establishing a secure HTTPS connection, the TLS negotiation occurs within the overall connection window. The API exposes this sub-phase using:
secureConnectionStart: The timestamp immediately before the browser initiates the TLS handshake.
Because TLS negotiation happens after the initial TCP three-way
handshake, secureConnectionStart divides the overall
connect window into two distinct segments:
Pure TCP Handshake Time:
const tcpDuration = resource.secureConnectionStart - resource.connectStart;TLS Negotiation Time:
const tlsDuration = resource.connectEnd - resource.secureConnectionStart;
If HTTPS is not used, or if a persistent connection is reused (such
as in HTTP/2 or HTTP/3 multiplexing), secureConnectionStart
returns 0, indicating that no new cryptographic handshake
was required.
The Timing-Allow-Origin Requirement
For security and privacy reasons, cross-origin resources do not
expose these granular network phases by default; the timestamps will be
reported as 0. To grant the consuming web page access to
DNS, TCP, and TLS metrics for third-party assets (such as CDNs, fonts,
or external scripts), the external server must send the following HTTP
response header:
Timing-Allow-Origin: *
Or restrict it to specific origins:
Timing-Allow-Origin: https://yourdomain.com
With this header present, developers can accurately break down the initial connection phases across all site assets to pinpoint network latency issues effectively.