Free Ebook cover Web Servers 101: How HTTP, DNS, TLS, and Reverse Proxies Work

Web Servers 101: How HTTP, DNS, TLS, and Reverse Proxies Work

New course

13 pages

Practical Troubleshooting: Using curl, dig, and Browser DevTools to Debug

Capítulo 13

Estimated reading time: 12 minutes

+ Exercise

What “practical troubleshooting” means in web debugging

When a site “doesn’t work,” the failure can be anywhere from name resolution to TLS negotiation to HTTP routing to application behavior in the browser. Practical troubleshooting is the habit of turning a vague symptom (“it’s down,” “login is broken,” “CORS error”) into a precise, testable statement (“DNS returns NXDOMAIN from our corporate resolver,” “TLS fails due to missing intermediate,” “the reverse proxy returns 502 after 30s,” “the browser blocks the response because the preflight is denied”).

This chapter focuses on three tools that complement each other:

  • curl: a programmable HTTP client for checking requests, responses, redirects, headers, cookies, compression, and timing—without browser complexity.
  • dig: a DNS query tool to verify which records exist, which resolver answers, and whether results differ by location or resolver.
  • Browser DevTools: the ground truth for what the browser actually did (requests, caching, cookies, CORS, mixed content, service workers, and JavaScript errors).

The goal is not to memorize flags, but to follow a repeatable workflow: isolate the layer, reproduce with the simplest tool, and compare “expected vs observed.”

A repeatable workflow: isolate, reproduce, compare

1) Start with the symptom and reduce it

Write down: the exact URL, what you expected, what you saw, and whether it fails for everyone or only some users/networks. If possible, get a single failing request (URL + method + headers) from DevTools and try to reproduce it with curl.

2) Check DNS quickly with dig

If the hostname can’t be resolved, nothing else matters. Even when it resolves, DNS can be “partially broken” (wrong record type, stale records, split-horizon differences, CDN misconfiguration).

Continue in our app.

You can listen to the audiobook with the screen off, receive a free certificate for this course, and also have access to 5,000 other free online courses.

Or continue reading below...
Download App

Download the app

3) Check HTTP behavior with curl

curl lets you see redirects, status codes, headers, and timing without browser caching, extensions, or JavaScript. It’s ideal for verifying what the server (or reverse proxy) returns.

4) Validate browser-specific constraints with DevTools

Many issues only exist in the browser: CORS enforcement, cookie SameSite rules, mixed content blocking, service worker caching, and preflight requests. DevTools shows the browser’s perspective and the exact reason for blocks.

Using dig to debug DNS issues

Common DNS symptoms you can confirm with dig

  • NXDOMAIN: the name doesn’t exist (typo, missing record, wrong zone).
  • No answer: the zone exists but the record type doesn’t (e.g., you query AAAA but only A exists).
  • Wrong IP: record points to old infrastructure or incorrect target.
  • Different answers from different resolvers: split-horizon DNS, geo DNS, or inconsistent propagation.
  • CNAME chain problems: CNAME points to a name that doesn’t exist or is blocked by policy.

Step-by-step: verify A/AAAA and compare resolvers

Query the A record (IPv4) and AAAA record (IPv6):

dig example.com A +noall +answer
dig example.com AAAA +noall +answer

If AAAA is present but your IPv6 path is broken, some clients may fail while others succeed. If only A exists, IPv6-only clients (less common) may fail.

Compare answers from different resolvers (useful when users report “works on my home Wi‑Fi but not at work”):

dig example.com A @1.1.1.1 +noall +answer
dig example.com A @8.8.8.8 +noall +answer
dig example.com A @9.9.9.9 +noall +answer

If these differ, you likely have geo/split-horizon behavior or inconsistent records. If your corporate resolver differs from public resolvers, it may be overriding or caching stale data.

Step-by-step: inspect CNAME chains

CDNs and reverse proxies often use CNAMEs. To see the chain:

dig www.example.com CNAME +noall +answer

Then query the target name you get back. Repeat until you reach an A/AAAA. If the chain ends in NXDOMAIN, you’ve found the break.

Step-by-step: check TTL and propagation expectations

TTL indicates how long resolvers may cache the answer. View TTL in the answer section (it’s the number after the name):

dig api.example.com A +noall +answer

If you recently changed DNS and some users still hit the old IP, a high TTL or resolver caching is a likely cause. Your troubleshooting action is to confirm which IP a user’s resolver returns (ask them to run dig against their resolver, or test from a similar network).

Step-by-step: check authoritative vs recursive answers

If you suspect the authoritative zone is correct but recursive resolvers are wrong, query the authoritative nameservers directly (you can discover them via NS records):

dig example.com NS +noall +answer

Then query one of those NS servers:

dig api.example.com A @ns1.yourdnsprovider.net +noall +answer

If authoritative answers are correct but a recursive resolver is wrong, the issue is caching, resolver policy, or DNSSEC/validation problems (depending on your environment).

Using curl to debug HTTP behavior (without the browser)

Why curl is essential

curl gives you a controlled, scriptable way to test endpoints. You can see status codes, headers, redirects, cookies, compression, and timing. It’s also ideal for comparing behavior across environments (staging vs production) or across hosts (direct-to-origin vs via reverse proxy).

Step-by-step: get status, headers, and follow redirects

Start with a HEAD request to see headers quickly (not all servers support HEAD perfectly, but it’s a good first check):

curl -I https://www.example.com/

If you suspect redirects, follow them and show each hop:

curl -I -L https://www.example.com/

Common findings:

  • Unexpected 301/302 loops: often caused by mismatched scheme/host expectations behind a reverse proxy.
  • Redirect to wrong host: misconfigured canonical host or application base URL.
  • HTTP to HTTPS redirect missing: users may hit insecure URL and get blocked or see mixed behavior.

Step-by-step: print the full exchange for one request

To see request headers you sent and response headers you received:

curl -v https://api.example.com/health

Look for:

  • Which IP you connected to (curl prints it): useful when DNS returns multiple addresses.
  • ALPN / HTTP version negotiation (h2 vs http/1.1) if relevant.
  • Response headers like Server, Via, X-Request-Id, Cache-Control that hint at which layer responded.

Step-by-step: test a specific method, body, and content type

If a POST works in the browser but fails in curl (or vice versa), ensure you match method and headers:

curl -v -X POST https://api.example.com/login \
  -H 'Content-Type: application/json' \
  -d '{"email":"a@example.com","password":"secret"}'

If the server returns 415 Unsupported Media Type or 400 Bad Request, compare the browser’s request payload and headers in DevTools (Network tab) and replicate them.

Step-by-step: debug authentication and cookies

Many “works in browser, fails in curl” issues are missing cookies or auth headers. You can store and send cookies with a cookie jar:

curl -c cookies.txt -b cookies.txt -v https://app.example.com/

For token-based auth:

curl -v https://api.example.com/me \
  -H 'Authorization: Bearer YOUR_TOKEN'

If you get 401/403, check whether the browser is sending additional headers (like a CSRF token) or whether the token is scoped to a different audience/environment.

Step-by-step: check CORS-related responses (server side)

CORS is enforced by browsers, but the server must return the right headers. With curl you can simulate the browser’s “Origin” header and inspect the response:

curl -I https://api.example.com/data \
  -H 'Origin: https://app.example.com'

For endpoints that require preflight, simulate an OPTIONS preflight:

curl -i -X OPTIONS https://api.example.com/data \
  -H 'Origin: https://app.example.com' \
  -H 'Access-Control-Request-Method: POST' \
  -H 'Access-Control-Request-Headers: content-type, authorization'

You’re looking for headers like Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers. If the server returns a 404/405 for OPTIONS, the browser will block the real request even if the POST endpoint works when called directly.

Step-by-step: isolate reverse proxy vs origin issues

If you can reach the origin directly (internal DNS or IP), compare responses:

curl -I https://public.example.com/
curl -I http://10.0.0.25:8080/

If the origin returns 200 but the public endpoint returns 502/504, the reverse proxy/load balancer path is the likely culprit (upstream health, routing, timeouts, TLS to upstream, header size limits).

If you can’t access the origin directly, you can sometimes force curl to connect to a specific IP while keeping the Host header (useful when DNS is wrong or you want to test a specific backend):

curl -v --resolve api.example.com:443:203.0.113.10 https://api.example.com/health

This helps answer: “Is the problem DNS (wrong IP) or the service at that IP?”

Step-by-step: measure timing to spot latency vs server processing

curl can output timing breakdowns. This is useful when users report slowness and you want to separate connection/setup from server time:

curl -o /dev/null -s -w 'dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n' https://www.example.com/

Interpretation examples:

  • High dns: resolver issues or slow network to DNS.
  • High connect: network path or server not accepting connections promptly.
  • High tls: TLS negotiation delays (could be packet loss, handshake retries, or server load).
  • High ttfb with low connect/tls: server-side processing or upstream dependency delays.

Using Browser DevTools to debug what the browser is doing

Network panel: your primary source of truth

Open DevTools → Network, then reload the page with the panel open. Key practices:

  • Disable cache (checkbox) while DevTools is open to avoid chasing cached responses.
  • Preserve log to keep requests across navigations and redirects.
  • Filter by “Fetch/XHR” to focus on API calls, or by status code (e.g., “404”, “500”).

Step-by-step: identify the failing request and read it precisely

Click the failing request and inspect:

  • Headers: Request URL, method, request headers, response headers.
  • Response: body returned (often includes error details).
  • Timing: stalled/queued time vs waiting (TTFB) vs download.
  • Initiator: which script or resource triggered it (helps locate the code path).

Then reproduce the same request with curl. Copy as cURL is often available in the context menu; if you use it, still verify it includes the same cookies/headers you expect.

Step-by-step: debug caching and “why didn’t my change deploy?”

Symptoms: you deployed a fix but the browser still runs old JavaScript/CSS. In Network:

  • Check whether the resource is served from (memory cache) or (disk cache).
  • Inspect Cache-Control, ETag, and Last-Modified response headers.
  • Look at the Size column; cached resources often show “(from disk cache)” rather than a byte size.

Practical steps:

  • Enable “Disable cache” and hard reload.
  • Open Application → Clear storage and clear site data if needed.
  • If a service worker is involved, check Application → Service Workers and update/unregister for testing.

Step-by-step: debug CORS errors (browser-enforced)

When the browser blocks a cross-origin request, the Network panel may show the request as failed or show an OPTIONS preflight. The Console usually includes a CORS message. Practical approach:

  • In Network, find the API request and see if there is an OPTIONS request right before it.
  • Click the OPTIONS request and inspect response headers for the expected Access-Control-Allow-* values.
  • Confirm the browser’s Request Headers include the Origin you expect.

Then validate server behavior with curl by simulating Origin and preflight (as shown earlier). This “DevTools to curl” loop is one of the fastest ways to turn a browser-only error into a server-side fix.

Step-by-step: debug cookies, sessions, and SameSite issues

Symptoms: login works in one browser but not another, or works on same-site navigation but not in embedded contexts. Use:

  • Application → Storage → Cookies to inspect which cookies exist, their domain/path, Secure flag, HttpOnly, and SameSite.
  • Network → a request → Headers to see which cookies were sent in the request.

Practical checks:

  • If a cookie is missing on a request, verify its Domain and Path match the request URL.
  • If the site is HTTPS but the cookie lacks Secure, modern browsers may treat it differently depending on context.
  • If a cross-site request needs cookies, SameSite settings may prevent sending them; DevTools often shows warnings in the Issues tab.

Step-by-step: debug mixed content and blocked requests

If an HTTPS page loads an HTTP resource, browsers may block it. In DevTools:

  • Console will show mixed content warnings/blocks.
  • Network will show failed resource loads, often with a “blocked” reason.

Fix is typically to use HTTPS URLs for all subresources, or ensure the resource is available over HTTPS.

Step-by-step: debug JavaScript errors vs network errors

Not every “API failed” is a network problem. Use:

  • Console: uncaught exceptions, failed promise rejections, JSON parse errors.
  • Sources: set breakpoints around the fetch/XHR call and inspect variables.

Practical pattern: if Network shows a 200 response but the UI still breaks, check Console for runtime errors or unexpected response shapes. If Network shows (failed) with no status, suspect connectivity, DNS, TLS, ad blockers, or CORS blocks.

Putting it together: three common debugging playbooks

Playbook A: “Site is down” (users can’t load the page)

  • dig: confirm the hostname resolves and compare resolvers. If answers differ, identify which resolver your users are using.
  • curl -I -L: check whether you get a response, whether redirects loop, and what status code is returned.
  • DevTools: if some assets fail, identify whether it’s a single host (e.g., static assets domain) and whether failures are blocked/cached.

Playbook B: “API calls fail in browser but work in Postman/curl”

  • DevTools: find the failing XHR/fetch, check if there’s a preflight OPTIONS, and read the Console CORS message.
  • curl: simulate Origin and preflight to confirm missing/incorrect CORS headers or OPTIONS handling.
  • DevTools Application: verify cookies are being sent if the API relies on session cookies; check SameSite/Secure constraints.

Playbook C: “Only some users see the problem”

  • dig: compare DNS answers across resolvers and check whether multiple A/AAAA records exist (users may hit different backends).
  • curl --resolve: test specific IPs behind the hostname to see if one backend is misbehaving.
  • DevTools: check caching/service worker differences; confirm the exact build/assets loaded by affected users.

Practical reference: a minimal command set to keep handy

dig essentials

dig example.com A +noall +answer
dig example.com AAAA +noall +answer
dig www.example.com CNAME +noall +answer
dig example.com NS +noall +answer
dig example.com A @1.1.1.1 +noall +answer

curl essentials

curl -I https://example.com/
curl -I -L https://example.com/
curl -v https://example.com/
curl -o /dev/null -s -w 'dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n' https://example.com/
curl -v --resolve example.com:443:203.0.113.10 https://example.com/

DevTools essentials

  • Network: Disable cache, Preserve log, filter by XHR/Fetch, inspect Headers/Timing/Initiator.
  • Console: read the exact error; distinguish CORS/mixed content blocks from application exceptions.
  • Application: inspect cookies, clear storage, check service workers and caches.
  • Issues tab (Chrome): centralized view of cookie, CORS, mixed content, and deprecation problems.

Now answer the exercise about the content:

When an API call fails in the browser but works with curl, what is the most effective next step to isolate a likely browser-only cause?

You are right! Congratulations, now go to the next page

You missed! Try again.

Browser-only failures often come from CORS enforcement, preflight OPTIONS handling, or cookie SameSite and Secure rules. DevTools shows what the browser blocked, and curl can then simulate Origin and preflight to confirm missing or incorrect server headers.

Next chapter

Arrow Right Icon
Download the app to earn free Certification and listen to the courses in the background, even with the screen off.