C#
JSON
WebRequest
System.Net
API Response

How to get json response using system.net.webrequest in c?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

When working with REST APIs in C#, you need a way to send HTTP requests and parse the JSON that comes back. The System.Net.WebRequest class was the original approach for making HTTP calls in .NET. While HttpClient is now the recommended choice for new projects, understanding WebRequest is still valuable for maintaining legacy codebases and for grasping how HTTP communication works at a lower level in .NET.

Setting Up an HttpWebRequest

WebRequest.Create returns a WebRequest instance, which you cast to HttpWebRequest to access HTTP-specific properties like Method, ContentType, and Accept. Setting the Accept header to application/json tells the server you expect a JSON response.

csharp
1using System;
2using System.IO;
3using System.Net;
4
5public class ApiClient
6{
7    public static string GetJsonResponse(string url)
8    {
9        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
10        request.Method = "GET";
11        request.Accept = "application/json";
12        request.ContentType = "application/json";
13
14        using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
15        using (Stream stream = response.GetResponseStream())
16        using (StreamReader reader = new StreamReader(stream))
17        {
18            return reader.ReadToEnd();
19        }
20    }
21}

The using blocks ensure that the response, stream, and reader are disposed of properly. Neglecting disposal can cause connection pool exhaustion under load.

Deserializing the JSON Response

Raw JSON strings are rarely useful on their own. Use System.Text.Json (built into .NET Core and .NET 5+) or Newtonsoft.Json to convert the string into a strongly typed object.

csharp
1using System.Text.Json;
2
3public class User
4{
5    public int Id { get; set; }
6    public string Name { get; set; }
7    public string Email { get; set; }
8}
9
10// Using System.Text.Json
11string json = ApiClient.GetJsonResponse("https://api.example.com/users/1");
12User user = JsonSerializer.Deserialize<User>(json, new JsonSerializerOptions
13{
14    PropertyNameCaseInsensitive = true
15});
16Console.WriteLine($"Name: {user.Name}, Email: {user.Email}");

If you are on .NET Framework (not .NET Core), you can use Newtonsoft.Json instead:

csharp
using Newtonsoft.Json;

User user = JsonConvert.DeserializeObject<User>(json);

Setting PropertyNameCaseInsensitive = true in System.Text.Json handles the common case where the API returns camelCase keys (name) but your C# properties use PascalCase (Name).

Handling Errors

WebRequest throws a WebException when the server returns a non-success status code. You should catch this exception, read the error response body, and handle it appropriately.

csharp
1public static string SafeGetJson(string url)
2{
3    try
4    {
5        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
6        request.Method = "GET";
7        request.Accept = "application/json";
8
9        using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
10        using (StreamReader reader = new StreamReader(response.GetResponseStream()))
11        {
12            return reader.ReadToEnd();
13        }
14    }
15    catch (WebException ex)
16    {
17        if (ex.Response is HttpWebResponse errorResponse)
18        {
19            using (StreamReader reader = new StreamReader(errorResponse.GetResponseStream()))
20            {
21                string errorBody = reader.ReadToEnd();
22                Console.Error.WriteLine(
23                    $"HTTP {(int)errorResponse.StatusCode}: {errorBody}"
24                );
25            }
26        }
27        else
28        {
29            Console.Error.WriteLine($"Network error: {ex.Message}");
30        }
31        return null;
32    }
33}

The WebException.Response property gives you access to the full error response, including the status code and body, which often contains a JSON error message from the API.

The Modern Alternative With HttpClient

For new code, HttpClient is simpler, supports async/await, and handles connection pooling more efficiently. Here is the equivalent operation:

csharp
1using System.Net.Http;
2using System.Text.Json;
3using System.Threading.Tasks;
4
5public class ModernApiClient
6{
7    private static readonly HttpClient _client = new HttpClient();
8
9    public static async Task<User> GetUserAsync(string url)
10    {
11        HttpResponseMessage response = await _client.GetAsync(url);
12        response.EnsureSuccessStatusCode();
13
14        string json = await response.Content.ReadAsStringAsync();
15        return JsonSerializer.Deserialize<User>(json, new JsonSerializerOptions
16        {
17            PropertyNameCaseInsensitive = true
18        });
19    }
20}

Notice that HttpClient is instantiated once and reused. Creating a new HttpClient per request is a well-known mistake that leads to socket exhaustion. If you are on .NET Core 2.1 or later, consider using IHttpClientFactory for even better lifecycle management.

Common Pitfalls

  • Not disposing the response and streams: HttpWebResponse holds a network connection. If you skip the using block or forget to call Close(), connections leak and eventually the application cannot make new requests.
  • Creating a new HttpClient per request: This applies to the modern alternative. Each instance holds its own connection pool, and rapid creation/disposal exhausts available sockets. Declare HttpClient as a static or singleton.
  • Ignoring non-success status codes with WebRequest: GetResponse() throws WebException for 4xx/5xx codes. If you catch and swallow the exception without reading the error body, you lose the server's error details.
  • Hardcoding http:// instead of https://: Modern APIs require TLS. Using plain HTTP either fails or exposes credentials in transit. Always default to HTTPS unless you have a specific reason for plain HTTP.
  • Assuming JSON property names match C# conventions: APIs typically use camelCase or snake_case. Without PropertyNameCaseInsensitive = true or [JsonPropertyName] attributes, deserialization silently produces null or default values for mismatched properties.

Summary

  • Use WebRequest.Create cast to HttpWebRequest to configure HTTP method, headers, and content type for JSON API calls.
  • Read the response by wrapping GetResponseStream() in a StreamReader inside using blocks to prevent connection leaks.
  • Deserialize JSON with System.Text.Json.JsonSerializer.Deserialize\<T> or Newtonsoft.Json.JsonConvert.DeserializeObject\<T>.
  • Catch WebException and inspect ex.Response to extract HTTP status codes and error bodies from failed requests.
  • For new projects, prefer HttpClient with a singleton or factory pattern for cleaner async code and proper connection management.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.