Your curl Has a Hidden Latency Profiler
One flag turns curl into a diagnostic tool that breaks down DNS, TCP, TLS, and transfer time.
You fire off a request. It takes 800ms. Your service logs say the handler ran in 12ms. So where did the other 788ms go?
Most developers reach for browser DevTools or Wireshark at this point. But the answer is already in your terminal — you just need to ask curl the right question.
Why this matters
In production, "the API is slow" is rarely one thing. It could be DNS resolution, TCP handshake, TLS negotiation, a slow server response, or network transfer. Without knowing which phase is the bottleneck, you're guessing.
curl's --write-out flag prints timing data for every stage of the request lifecycle. No extra tools. No plugins. No browser tab.
How it works
Pass -w with format variables, and curl prints them to stdout after the transfer completes. The timing variables that matter:
time_namelookup— DNS resolution durationtime_connect— TCP handshake completiontime_appconnect— TLS handshake completiontime_starttransfer— time to first byte received (TTFB)time_total— full request duration
Each value is in seconds, precise to the millisecond. The trick is subtraction. If time_namelookup is 400ms, DNS is your problem. If the gap between time_appconnect and time_starttransfer is 600ms, the server is slow. If time_total dwarfs time_starttransfer, it's payload size or bandwidth.
Where this helps
Debugging "the API is slow" — Compare TTFB against total time to instantly separate server-side processing from network overhead.
Investigating TLS cost — The gap between time_connect and time_appconnect shows exactly how long the handshake takes. Useful when evaluating mTLS or cert pinning overhead.
DNS troubleshooting — If time_namelookup spikes intermittently across requests, you have a resolver problem, not an application problem.
Comparing CDN regions — Run the same request against multiple regional endpoints and compare timing breakdowns side by side.
Watch out
The -w output goes to stdout and collides with the response body. Always pair it with -o /dev/null to discard the body. Use single quotes around the format string so your shell doesn't eat the % variables. And remember: curl only sees the client side. Server-internal breakdowns are lumped into TTFB with no further detail.
Try it yourself
curl -o /dev/null -s -w "DNS: %{time_namelookup}s\nTCP: %{time_connect}s\nTLS: %{time_appconnect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" https://api.github.com/users/torvaldsTL;DR
- What: curl's
-wflag exposes per-phase timing for every request. - Why: It isolates DNS, TCP, TLS, TTFB, and transfer time with zero extra tooling.
- Try: Run the snippet above against any endpoint that feels slow.