.Net HttpWebRequest.GetResponse raises exception when http status code 400 bad request is returned
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
HttpWebRequest.GetResponse() throws a WebException for HTTP 4xx and 5xx responses by design. That includes 400 Bad Request. The key point is that the response still exists; you just have to read it from the exception instead of expecting GetResponse() to return normally.
Why the Exception Happens
HttpWebRequest treats non-success HTTP status codes as request failures and surfaces them through WebException. So code like this will throw when the server responds with 400:
This behavior often surprises developers who expect the method to return an object for every HTTP response. But the .NET API deliberately forces error handling through exceptions for these status ranges.
Catch WebException and Read the Response
The normal pattern is to catch WebException, then inspect the attached response.
That gives you both the status code and the error payload returned by the server.
The Response Body Often Contains the Real Clue
A 400 Bad Request usually means the client sent something malformed or incomplete. The exception itself only tells you that the request failed. The response body often contains the useful explanation, such as:
- missing required field
- invalid JSON syntax
- bad query parameter format
- unsupported media type details from the server
That is why reading the response stream is often more important than reading the exception message.
Check Method, Headers, and Body
If you are getting 400, the real bug is usually in the request shape. Common issues include:
- wrong HTTP method
- incorrect
ContentType - malformed body payload
- missing authentication or custom headers
- wrong query string encoding
For example, when sending JSON, do not forget the content type and body write:
If the body format does not match what the server expects, 400 is a common result.
HttpWebRequest Is Legacy API
For new code, HttpClient is usually the better choice. It does not force error responses through the same legacy pattern, and it is generally easier to use.
With HttpClient, you decide whether to call EnsureSuccessStatusCode() or handle non-success statuses manually.
Distinguish Transport Failures from HTTP Failures
A 400 is not a network failure. It means the server responded and rejected the request. That is very different from DNS failure, timeout, or connection refusal.
This distinction matters when logging and retrying. Retrying a malformed request usually just repeats the same mistake.
Common Pitfalls
- Assuming
GetResponse()should return normally even for400responses. - Catching
WebExceptionbut never readingex.Response. - Looking only at the exception message and ignoring the error body from the server.
- Retrying a
400response as if it were a transient network problem. - Continuing to use
HttpWebRequestin new code whenHttpClientwould be simpler.
Summary
- '
HttpWebRequest.GetResponse()throwsWebExceptionfor HTTP 4xx and 5xx responses by design.' - For
400 Bad Request, the response still exists and can be read fromex.Response. - The response body often explains what was wrong with the request.
- Most
400bugs come from malformed URLs, headers, or body content. - In new .NET code,
HttpClientis usually the better API.

