C#
webClient
DownloadFile
timeout
programming

Set timeout for webClient.DownloadFile

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

The WebClient class in .NET does not expose a Timeout property, which makes it difficult to control how long DownloadFile waits before giving up on a slow or unresponsive server. The default timeout is 100 seconds, inherited from the underlying HttpWebRequest. This article shows several approaches to set a custom timeout for file downloads.

The Problem

csharp
1// WebClient has no Timeout property
2var client = new WebClient();
3// client.Timeout = 5000; // Does not compile!
4client.DownloadFile("https://example.com/largefile.zip", "output.zip");

If the server is slow, this will block for up to 100 seconds before throwing a WebException.

Solution 1: Subclass WebClient (Quick Fix)

Override GetWebRequest to set the timeout on the underlying HttpWebRequest:

csharp
1public class WebClientWithTimeout : WebClient
2{
3    public int Timeout { get; set; } = 100000; // Default 100 seconds (in ms)
4
5    protected override WebRequest GetWebRequest(Uri uri)
6    {
7        var request = base.GetWebRequest(uri);
8        request.Timeout = Timeout;
9        return request;
10    }
11}
12
13// Usage
14var client = new WebClientWithTimeout { Timeout = 5000 }; // 5 seconds
15client.DownloadFile("https://example.com/file.zip", "output.zip");

This is the simplest approach and works well for most scenarios.

WebClient is deprecated in .NET 6+. Use HttpClient instead, which has built-in timeout support:

csharp
1using var httpClient = new HttpClient
2{
3    Timeout = TimeSpan.FromSeconds(30)
4};
5
6// Download to file
7using var response = await httpClient.GetAsync("https://example.com/file.zip");
8response.EnsureSuccessStatusCode();
9
10using var fileStream = File.Create("output.zip");
11await response.Content.CopyToAsync(fileStream);

With Progress Reporting

csharp
1using var httpClient = new HttpClient { Timeout = TimeSpan.FromMinutes(5) };
2using var response = await httpClient.GetAsync(
3    "https://example.com/file.zip",
4    HttpCompletionOption.ResponseHeadersRead
5);
6response.EnsureSuccessStatusCode();
7
8var totalBytes = response.Content.Headers.ContentLength ?? -1;
9using var contentStream = await response.Content.ReadAsStreamAsync();
10using var fileStream = File.Create("output.zip");
11
12var buffer = new byte[8192];
13long totalRead = 0;
14int bytesRead;
15
16while ((bytesRead = await contentStream.ReadAsync(buffer)) > 0)
17{
18    await fileStream.WriteAsync(buffer.AsMemory(0, bytesRead));
19    totalRead += bytesRead;
20
21    if (totalBytes > 0)
22    {
23        var progress = (double)totalRead / totalBytes * 100;
24        Console.Write($"\rDownloading: {progress:F1}%");
25    }
26}
27Console.WriteLine("\nDone!");

Solution 3: Use HttpWebRequest Directly

For full control over timeouts (connection and read separately):

csharp
1public static void DownloadFileWithTimeout(string url, string outputPath, int timeoutMs = 30000)
2{
3    var request = (HttpWebRequest)WebRequest.Create(url);
4    request.Timeout = timeoutMs;           // Time to establish connection
5    request.ReadWriteTimeout = timeoutMs;  // Time for data transfer
6
7    using var response = (HttpWebResponse)request.GetResponse();
8    using var responseStream = response.GetResponseStream();
9    using var fileStream = File.Create(outputPath);
10
11    var buffer = new byte[8192];
12    int bytesRead;
13    while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0)
14    {
15        fileStream.Write(buffer, 0, bytesRead);
16    }
17}
18
19// Usage
20DownloadFileWithTimeout("https://example.com/file.zip", "output.zip", 10000);

HttpWebRequest provides two timeout properties:

  • Timeout: Time to wait for the initial connection and response headers
  • ReadWriteTimeout: Time to wait for data during the read/write phase

Solution 4: CancellationToken with HttpClient (Async)

For async code, use a CancellationToken with a timeout:

csharp
1using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
2using var httpClient = new HttpClient();
3
4try
5{
6    using var response = await httpClient.GetAsync(url, cts.Token);
7    response.EnsureSuccessStatusCode();
8    using var fs = File.Create("output.zip");
9    await response.Content.CopyToAsync(fs, cts.Token);
10}
11catch (OperationCanceledException)
12{
13    Console.WriteLine("Download timed out!");
14}

This approach allows you to cancel the download at any point, not just during connection.

Comparison of Approaches

Approach.NET VersionAsyncGranular TimeoutDeprecated?
WebClient subclassAllNo*NoYes (.NET 6+)
HttpClient.NET Core+YesVia CancellationTokenNo
HttpWebRequestAllOptionalYes (connect + read)Yes (.NET 6+)

*WebClient has async methods but they are callback-based, not Task-based.

Common Pitfalls

  • WebClient is deprecated: In .NET 6+, WebClient is marked obsolete. Migrate to HttpClient for new projects.
  • HttpClient should be reused: Do not create a new HttpClient per request — this causes socket exhaustion. Use IHttpClientFactory or a single static instance.
  • Timeout vs CancellationToken: HttpClient.Timeout applies to the entire request (including reading the body). For large file downloads, set a generous timeout and use CancellationToken for user-initiated cancellation.
  • Large file memory: Using GetStringAsync or ReadAsByteArrayAsync loads the entire file into memory. Use ResponseHeadersRead and stream to file for large downloads.
  • Proxy and DNS: Timeout includes DNS resolution and proxy negotiation. On slow networks, the connection phase alone may consume most of the timeout budget.

Summary

  • Subclass WebClient and override GetWebRequest to set Timeout for a quick fix
  • Prefer HttpClient with Timeout property for new .NET Core+ projects
  • Use HttpWebRequest for separate connection and read/write timeouts
  • For large downloads, use streaming with ResponseHeadersRead to avoid loading the entire file in memory
  • WebClient is deprecated in .NET 6+ — migrate to HttpClient

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

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

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.