How to check API response time
Run curl -s -o /dev/null -w '%{time_namelookup} %{time_connect} %{time_appconnect} %{time_starttransfer} %{time_total}\n' https://api.example.com/. Every number is seconds counted from the start of the request, so the gaps between them separate DNS, TCP, TLS and server think time. Take five samples, because one request is noise.
Why check this
A response time regression arrives as a ticket that says the app feels slow, with no layer named. Run this breakdown on staging before sign-off, and again after any infrastructure change: a new load balancer, a DNS provider swap, a certificate rotation. The five numbers tell you which team owns the regression. A 90 ms TLS handshake is not the API team's bug, and a time_starttransfer that sits 400 ms after time_appconnect is not the network team's bug either.
Prerequisites
- curl 7.0 or later. The
-wwrite-out variables used here have shipped since 7.9. See the curl manual on --write-out. - The endpoint URL with whatever auth header it needs, so the server does real work instead of returning 401 in 2 ms.
- A machine that is not running the build at the same time. Local CPU contention shows up as server time and sends you hunting in the wrong place.
Steps
- Step 1.
Request the endpoint once and print the five timing marks.
curl -s -o /dev/null -w 'dns %{time_namelookup}\ntcp %{time_connect}\ntls %{time_appconnect}\nttfb %{time_starttransfer}\ntotal %{time_total}\n' https://example.com/dns 0.012902 tcp 0.044262 tls 0.087263 ttfb 0.123651 total 0.123751Each value is cumulative. DNS took 13 ms, the TCP handshake added 31 ms, the TLS handshake added 43 ms, the server answered 36 ms later, and the body finished 0.1 ms after the first byte.
- Step 2.
Repeat the request five times and read the spread, not the average.
for i in 1 2 3 4 5; do curl -s -o /dev/null -w "$i %{time_namelookup} %{time_connect} %{time_appconnect} %{time_starttransfer} %{time_total}\n" https://example.com/; done1 0.008890 0.050523 0.091733 0.125147 0.125283 2 0.004757 0.033579 0.071862 0.104567 0.104729 3 0.004729 0.033059 0.075750 0.113771 0.113894 4 0.019789 0.051263 0.102031 0.143564 0.143694 5 0.012504 0.041496 0.080000 0.111186 0.111280Total ran from 105 ms to 144 ms across the five, a spread of 39 ms on an endpoint that did nothing. Any single measurement you quote in a bug report has to survive that spread.
- Step 3.
Ask for two resources in one command so the second reuses the open connection.
curl -s -o /dev/null -o /dev/null -w '%{url} dns %{time_namelookup} tcp %{time_connect} tls %{time_appconnect} ttfb %{time_starttransfer} total %{time_total}\n' https://example.com/ https://example.com/index.htmlhttps://example.com/ dns 0.010585 tcp 0.042180 tls 0.088957 ttfb 0.121083 total 0.121227 https://example.com/index.html dns 0.000000 tcp 0.000000 tls 0.000000 ttfb 0.031645 total 0.031762On the reused connection curl reports zero for DNS, TCP and TLS, and total falls from 121 ms to 32 ms. The 89 ms difference is setup cost that a real client pays once per connection, not once per call.
How to read the result
| What you see | What it means | What to do |
| --- | --- | --- |
| time_namelookup is the largest jump | The resolver is slow or the record is uncached | Measure the resolver on its own before touching the API |
| time_connect minus time_namelookup is large | TCP setup is slow, so distance or packet loss | Compare from a second network, then look at the route |
| time_appconnect minus time_connect is large | The TLS handshake is the cost | Check the certificate chain length and the session resumption setting |
| time_starttransfer minus time_appconnect is large | The server is thinking | Hand the trace to the API team, the network is fine |
| time_total minus time_starttransfer is large | The body is slow to stream | Check the payload size and whether compression is on |
Common mistakes
What to check next
- How to check TTFB: the same
time_starttransfervalue, read as a page metric rather than an API one. - How to check DNS lookup time: isolate the first number when it is the one that moves.
- How to check if keep-alive is enabled: confirm the server lets clients skip the setup cost that step 3 measures.
- How to test API timeout handling: decide what the client does once the response time crosses the budget.
FAQ
How to check API latency without installing anything?
curl ships with Windows 10, macOS and most Linux images, so the command in step 1 runs as is. What varies between builds is protocol support, not the timing variables, which have been in curl since 7.9.
How to check API response time in Postman?
Postman shows one number next to the status code, which is the equivalent of time_total. It does not break the request into DNS, TCP and TLS, so a slow handshake and a slow handler look identical there. Use the curl breakdown to tell them apart.
What does curl time_total actually measure?
Seconds from the moment curl started the transfer to the moment the last byte of the body arrived, including redirects when -L is used. It excludes the time your shell spent starting curl.
Is an average of ten requests a better number?
An average hides the tail that users complain about. Report the slowest sample and the spread alongside the median. The five samples in step 2 differed by 39 ms with no change to the server.
How many samples are enough for a bug report?
Five from one location gives you a spread to quote. Anything about percentiles or sustained load needs a load tool, not curl in a loop, because a sequential loop never puts two requests on the server at once.
Verified
Verified by Maks Vernycurl 8.21.0
Each output block is what the command above it printed on that date, on the host named in the step. Figures read from a live site move between runs. Compare the shape of the answer rather than the digits, and see the methodology for how a page is re-verified.
Related on this site
basic5 minpublished updated Maks Verny