Network Troubleshooting for Developers Before Blaming Your Code
Our guides are based on hands-on testing and verified sources. Each article is reviewed for accuracy and updated regularly to ensure current, reliable information.Read our editorial policy.
When an API call fails, a page refuses to load, or a service suddenly times out, it is easy to assume the code is broken.
Sometimes it is. But many application failures actually begin lower in the stack: DNS, a blocked TCP port, TLS negotiation, a proxy, a VPN, an IPv6 route, a browser security policy, or an upstream service outage.
A better approach is to troubleshoot the connection layer by layer before changing working application code.
This guide provides a practical network troubleshooting workflow for developers, including the commands and tools you can use to isolate where a request is failing.
Network Troubleshooting Checklist
| Layer | What to Test | Useful Tools |
|---|---|---|
| Local connection | Is your device online and stable? | Browser, ping, speed test |
| DNS | Does the hostname resolve to the expected address? | nslookup, dig |
| TCP | Is the required port reachable? | Test-NetConnection, nc |
| TLS | Can HTTPS establish a secure connection? | curl -v |
| HTTP/API | Does the endpoint return the expected response? | curl |
| Browser | Is CORS, CSP, mixed content, or another browser rule blocking it? | DevTools Network panel |
| Route | Where does traffic travel or stop? | traceroute, tracert, pathping, mtr |
| Environment | Are a VPN, proxy, firewall, container, or cloud rule involved? | OS/network configuration |
| Application | How does the failing request differ from a working one? | Logs, HAR files, request comparison |
1. Start With Basic Connectivity
Begin with the simplest question: can your device reliably reach the internet or local network?
Open a known working website or test another service. This quickly tells you whether the problem is broad or limited to one destination.
If several unrelated services fail at the same time, investigate the local connection before looking at application code.
You can also try:
ping example.com
A successful ping confirms that ICMP replies are getting back to your device, but a failed ping does not prove that a server is offline. Firewalls and network devices often block ICMP while allowing HTTP, HTTPS, SSH, or other application traffic.
If you suspect connection quality rather than a complete outage, CodeItBro’s Internet Speed Test can measure download speed, upload speed, ping, and jitter.
High latency, packet instability, or a weak wireless connection can make an application feel unreliable even when the service itself is healthy.
2. Check DNS Resolution
Applications normally connect to hostnames such as:
api.example.com
Before the connection can begin, that hostname needs to resolve to an IP address.
On Windows, macOS, or Linux, you can start with:
nslookup api.example.com
On systems with dig installed:
dig api.example.com
Do not stop at “DNS returned an IP address.”
Ask two questions:
- Did the hostname resolve?
- Did it resolve to the address you expected?
A successful lookup can still return an unexpected or stale destination because of cached DNS records, split-horizon DNS, VPN-provided resolvers, old deployment records, or different geographic/CDN responses.
If you manage the domain, compare the answer with the authoritative DNS configuration. Cloudflare’s DNS troubleshooting guide also recommends verifying that hostnames point to the intended origin.
Check Both IPv4 and IPv6
Modern hostnames may return both:
- A records for IPv4;
- AAAA records for IPv6.
A service can work over IPv4 while failing over IPv6, or the reverse.
You can compare them with curl:
curl -4 https://api.example.com curl -6 https://api.example.com
If one works and the other fails consistently, investigate routing, DNS records, firewall rules, or the server’s IPv6 configuration.
3. Test the Required TCP Port
DNS can work perfectly while the application port is blocked.
For example, a server might respond to ping but reject connections to:
- 443 for HTTPS;
- 22 for SSH;
- 5432 for PostgreSQL;
- 3306 for MySQL;
- 6379 for Redis.
On Windows, PowerShell’s Test-NetConnection can test a specific TCP port:
Test-NetConnection api.example.com -Port 443
Look for:
TcpTestSucceeded : True
On macOS or Linux, Netcat is useful:
nc -vz api.example.com 443
If DNS works but the port test fails, possible causes include:
- a local firewall;
- a cloud security group;
- an outbound corporate firewall;
- an inbound server firewall;
- the service not listening on the expected port;
- a VPN or route problem.
4. Check TLS and HTTPS
A successful TCP connection does not guarantee that HTTPS will work.
The TLS handshake can fail because of:
- an expired certificate;
- a hostname mismatch;
- a missing certificate chain;
- an unsupported TLS configuration;
- incorrect system time;
- corporate TLS inspection;
- Server Name Indication issues.
A useful first test is:
curl -v https://api.example.com
The -v option displays connection details, request headers, response headers, and TLS information. The official curl documentation specifically recommends verbose output for debugging.
Be careful when sharing verbose logs because they may contain cookies, authorization headers, tokens, or other sensitive information.
If terms such as TLS, VPN, firewall, or access control are unfamiliar, CodeItBro’s Cybersecurity Glossary provides short technical definitions.
5. Test the Service Outside Your Application
Once DNS, TCP, and TLS look healthy, send the request without your application.
For a simple GET request:
curl -v https://api.example.com/health
If you want both the response headers and body:
curl -i https://api.example.com/health
One important distinction: this command:
curl -I https://api.example.com
sends an HTTP HEAD request, not a normal GET request.
The curl project’s HTTP scripting guide notes that some servers treat HEAD differently or reject it even when GET works normally.
So use -I when you specifically want to test HEAD or inspect headers. For application troubleshooting, reproduce the request as closely as possible.
That means matching:
- HTTP method;
- URL;
- query parameters;
- headers;
- authentication;
- content type;
- request body.
For example:
curl -v \
-X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TOKEN" \
-d '{"name":"test"}' \
https://api.example.com/v1/itemsHTTP 200 Does Not Mean the Operation Succeeded
A 200 OK response confirms that the server successfully returned an HTTP response.
It does not guarantee that the business operation worked.
The body might still contain:
- an application error;
- empty results;
- a failed validation state;
- unexpected data.
Always inspect both the status code and the response body.
6. Inspect the Request in Browser DevTools
If curl works but your web application fails, the browser itself may be part of the problem.
Open Chrome DevTools and go to the Network panel. Chrome’s official Network panel guide explains how to inspect requests, headers, payloads, responses, timing, cookies, and initiators.
For the failing request, check:
- request URL;
- HTTP method;
- status code;
- request headers;
- response headers;
- request payload;
- response body;
- redirects;
- cookies;
- timing.
The Network panel can also show whether the browser blocked the request before your application received a usable response.
7. Separate CORS Problems From Network Problems
A very common developer scenario looks like this:
curl works browser request fails
That often points away from basic network connectivity.
One possible cause is Cross-Origin Resource Sharing, or CORS.
Browsers apply the same-origin policy to JavaScript requests such as fetch() and XMLHttpRequest. A cross-origin API must return the appropriate CORS headers before the browser allows frontend JavaScript to access the response.
MDN’s CORS guide explains the mechanism and preflight requests in detail.
Other browser-specific causes can include:
- Content Security Policy;
- mixed-content blocking;
- SameSite or third-party cookie rules;
- browser extensions;
- privacy tools;
- service workers;
- cached application state.
Do not disable browser security controls permanently just to make a failing request work. Identify and correct the underlying configuration instead.
8. Check the Network Path
If DNS resolves and the service remains unreachable, inspect the route between your machine and the destination.
On macOS or Linux:
traceroute api.example.com
On Windows:
tracert api.example.com
Microsoft’s tracert documentation explains how Windows identifies intermediate hops.
Do not assume that a timeout at one hop proves that router is broken. Network devices often ignore diagnostic packets while still forwarding normal traffic.
Also remember that:
- forward and return routes can be different;
- load balancers can produce different paths;
- an intermediate hop may show high latency while later hops remain healthy.
For longer tests, Windows users can use pathping, while Linux and macOS users often use mtr to observe latency and packet loss over time.
9. Check VPN, Proxy, and Firewall Configuration
Your machine may not send traffic directly to the destination.
A VPN can change:
- routing;
- DNS servers;
- public IP address;
- MTU behavior;
- accessible private networks.
If a request works with the VPN disabled but fails when it is connected, that difference is an important troubleshooting signal.
A commercial VPN service, a corporate VPN, or a self-hosted tunnel can all alter the route a request takes, so always test the same request both with and without the tunnel when policy permits.
Proxy servers can also change request behavior. Check:
HTTP_PROXY;HTTPS_PROXY;- operating-system proxy settings;
- browser proxy settings;
- corporate gateway configuration.
For more background on forward proxies, outbound routing, and traffic inspection, see CodeItBro’s guide to proxy server use cases.
Also check firewalls at every relevant layer:
- local operating-system firewall;
- router firewall;
- corporate network firewall;
- cloud security group;
- cloud network ACL;
- server firewall;
- container or Kubernetes network policy.
10. Check Whether the Service Itself Is Healthy
Sometimes neither your code nor your network is responsible.
The remote service may simply be degraded.
Check:
- the provider’s status page;
- recent incident reports;
- your server or API logs;
- load balancer health checks;
- deployment status;
- database health;
- rate limits or quotas;
- upstream dependencies.
Pay attention to HTTP status codes such as:
- 429 — rate limited;
- 502 — bad gateway;
- 503 — service unavailable;
- 504 — gateway timeout.
For production environments where one-off testing is no longer enough, CodeItBro’s guide to network monitoring tools covers software for continuous visibility and alerting.
11. Compare a Working Request With a Failed One
Once lower-level connectivity is confirmed, compare the failing request with one that works.
Look for differences in:
- hostname;
- scheme: HTTP vs HTTPS;
- port;
- path;
- HTTP method;
- query parameters;
- headers;
- authentication;
- cookies;
- request body;
- timeout;
- proxy configuration.
If a request works in curl but not in your application, compare exactly what each client sends.
In browser-based applications, Chrome DevTools can copy a request as curl, which makes this particularly useful.
Change one variable at a time. If you change the URL, headers, timeout, and authentication simultaneously, you may fix the problem without learning what actually caused it.
12. Check Application and Server Logs
Network tests tell you whether a connection can be established. Logs tell you what happened after the request reached the application.
Useful client-side information includes:
- exception type;
- request timeout;
- DNS error;
- connection refusal;
- TLS error;
- retry count.
Server logs can reveal:
- whether the request arrived;
- which route handled it;
- authentication failures;
- upstream timeouts;
- database failures;
- rate-limit decisions;
- application exceptions.
If the client reports a timeout but the server never logs the request, the problem is likely somewhere before the application.
If the server logs the request and throws an exception, debugging the application becomes much more relevant.
A Practical Network Troubleshooting Order
When a request fails, this sequence keeps the investigation focused:
- Scope the issue. Is one endpoint failing or everything?
- Check local connectivity. Confirm the device has a stable network connection.
- Resolve DNS. Make sure the hostname maps to the expected IP.
- Test the TCP port. Confirm the service port is reachable.
- Check TLS. Verify HTTPS can complete its handshake.
- Send the request with curl. Reproduce the actual HTTP request.
- Inspect browser DevTools. Check CORS, cookies, headers, payloads, and timing.
- Trace the route. Investigate routing only when lower-layer evidence points there.
- Test environment differences. Compare VPN, proxy, firewall, IPv4, and IPv6 behavior.
- Check service health. Look at provider status and server-side logs.
- Compare requests. Find the smallest difference between working and failed cases.
- Change one variable at a time. Keep the troubleshooting process reproducible.
Common Symptoms and What to Check First
| Symptom | Check First |
|---|---|
| Hostname not found | DNS resolution |
| Connection refused | Service process and TCP port |
| Connection timeout | Firewall, routing, VPN, service health |
| Certificate error | TLS certificate, hostname, system clock |
| curl works but browser fails | CORS, CSP, cookies, mixed content |
| Works without VPN | VPN routes, DNS, MTU, firewall policy |
| Works on IPv4 only | AAAA record, IPv6 routing, firewall |
| HTTP 401 | Authentication |
| HTTP 403 | Authorization, WAF, security policy |
| HTTP 404 | URL, path, deployment, routing |
| HTTP 429 | Rate limit or quota |
| HTTP 502/503/504 | Upstream service or infrastructure |
Final Thoughts
Good network troubleshooting is mostly about isolation.
Do not start rewriting application code because one request failed. First determine which layer is actually broken.
Check basic connectivity, DNS, the destination port, TLS, and the service independently. Then inspect the browser, routing, VPNs, proxies, firewalls, and server health.
If all of those layers behave correctly but the application still fails, you have much stronger evidence that the problem belongs in the code.
The goal is not to run every networking command you know. It is to perform the smallest test that rules out one layer at a time, record the result, and move deeper only when the evidence justifies it.


