2時間。407 Proxy Authentication Required という1行のレスポンスを前に、私が無駄にした時間です。最初はプロキシ業者を疑い、設定をあれこれ見直し、ログをにらみ続けました。ところが犯人は、資格情報を渡すプロパティの取り違え。直すべきはたった2行だったのです。この苦い思い出に身に覚えがあるなら、ぜひ読み進めてください。
C# の HttpClient でプロキシをつなぐだけなら、型が決まっているので拍子抜けするほど簡単です。本当の戦いが始まるのは本番投入後。ソケット枯渇、SOCKS5 のバージョン差、そして先ほどの認証情報の置き場所——こうした地雷が、あなたの時間を少しずつ削っていきます。
私は Thunderbit で長年 Web スクレイピングとデータ抽出のツールづくりに関わってきました。今回挙げるようなつまずきは、自社の技術レビューの席でも、日々ウォッチしている開発者コミュニティでも、数えきれないほど見てきたものばかりです。以下では、初期セットアップ、認証、ローテーション、プロトコルの選択、そして手元に置いておきたいトラブルシューティング表まで、順を追って整理します。
難易度: 初級〜中級
所要時間: 理解するだけなら15分ほど。本番向けのローテーション設計まで含めると、もう少し見ておきましょう
用意するもの: .NET 6 以上の SDK(SOCKS5 と最新の handler 機能を使うため。基本的な HTTP プロキシの例なら .NET Framework 4.x でも動きます)、コードエディタ、そして動作確認用のプロキシエンドポイントを1つ以上
HttpClient とは何か、なぜプロキシが要るのか

HttpClient は、System.Net.Http 名前空間に属する .NET 標準の HTTP 通信クラスです。HTTP リクエストを送り、レスポンスを受け取る役目を担い、async/await、カスタムヘッダー、キャンセルトークン、handler ベースの設定にも対応します。Microsoft 自身も、URI で識別されるリソースに HTTP リクエストを送り、HTTP 応答を受け取るためのクラス だと説明しています。
プロキシサーバーは、アプリと対象サイトの間に立つ仲介役です。通信をプロキシ経由にすると、対象サイトからはあなたの IP ではなく、プロキシの IP が見えるようになります。
注意したいのは、HttpClient そのものには Proxy プロパティがないという点です。プロキシのルーティングは、内部で動く handler——HttpClientHandler または SocketsHttpHandler——に対して設定します。これらは WebProxy インスタンスを受け取ります。流れを図にすると、こんな具合です。
[あなたの C# アプリ] → [HttpClient + Handler] → [プロキシサーバー] → [対象サイト]
ですから「稼働中の HttpClient のプロキシを差し替える」というのは、ただプロパティをいじる話ではなく、設計レベルの課題になります。これはローテーションの章で掘り下げます。
C# の HttpClient でプロキシを使う理由
開発者が HttpClient の通信をプロキシ経由にする動機は、おおむね決まっています。そして、どのプロキシを選ぶかは用途しだいです。
- IP ブロックやレート制限をかわす: 大規模な Web スクレイピング、リード獲得、価格監視では欠かせません。同じ IP でサイトを叩き続ければ、たいていすぐに弾かれます。
- 地域制限を回避する: 特定の国のプロキシを使えば、その地域限定の API やコンテンツに手が届きます。
- 発信元 IP を隠す: 機微なデータ収集や競合調査で、プライバシーをもう一段引き上げられます。
- 企業やコンプライアンスの要請: 多くの企業では、送信トラフィックを中央ゲートウェイにまとめ、ログ取得や統制をかける必要があります。
- テストと QA: 現地にインフラを置かなくても、別の地域やネットワーク条件からのアクセスを再現できます。
| ユースケース | 一般的なプロキシの選択 | 向いている理由 |
|---|---|---|
| 大規模 Web スクレイピング | ローテーション型住宅用プロキシ | IP の多様性が高く、ボット対策に分類されにくい |
| EC の価格監視 | 住宅用または地域指定型データセンタープロキシ | 地域別価格や在庫確認に適している |
| 固定ゲートウェイ経由の API アクセス | データセンタープロキシまたは社内プロキシ | IP の許可リスト管理がしやすく、コストも低い |
| 企業のコンプライアンス対応 | システムプロキシ、PAC プロキシ、認証付き社内プロキシ | 集中ログ管理と送信制御がしやすい |
| QA とローカライズ検証 | 国別プロキシプール | 対象地域の実ユーザーアクセスを再現できる |
プロキシの使い方は、段階を追ってスケールしていくのが普通です。まずは単一の静的プロキシでルーティングを確かめ、本番のスクレイパーでは対象ドメイン・地域・失敗率などでプロキシプールを振り分けます。チームが成熟してくると、ローテーション・リトライ・セッション固定を1つのエンドポイントの裏でまとめてさばく管理型プロキシゲートウェイへ移ることも多いです。
ただし、プロキシローテーションは万能の特効薬ではありません。対象サイトが不審な挙動そのものを弾いている場合、IP を取り替えるだけでは足りません。リクエスト頻度、ヘッダー、Cookie、TLS フィンガープリントまで、ていねいに整える必要があります。
どの .NET バージョンで何が使えるか: 互換性の早見表
ブログ記事のプロキシコードを、別のターゲットフレームワークにそのまま貼り付ける——これは失敗の温床です。とりわけ大きな分かれ目が、.NET Framework 4.x とモダンな .NET(.NET 6 以降)の違いです。対応状況をまとめました。

| 機能 | .NET Framework 4.x | .NET 6 | .NET 7 | .NET 8–9 |
|---|---|---|---|---|
WebProxy + HttpClientHandler | あり | あり | あり | あり |
WebProxy("socks5://..." ) による SOCKS5 | なし | あり (.NET 6 で追加) | あり | あり |
SocketsHttpHandler(既定の handler) | なし | あり | あり | あり |
HttpClient.DefaultProxy の static プロパティ | なし | あり | あり | あり |
PooledConnectionLifetime | なし | あり | あり | あり |
.NET Framework 4.x を相手にするなら、HttpClientHandler と WebProxy を使った HTTP/HTTPS プロキシに絞っておくのが無難です。SOCKS5 や最新の pooling 制御を使いたいなら、.NET 6 以上が前提になります。
もう1つ、見落としがちな挙動があります。モダン .NET では HttpClient.DefaultProxy は static プロパティです。共有の起動コードや、HTTPS_PROXY / HTTP_PROXY のような環境変数で設定されていると、handler で明示的に上書きしない限り、すべての HttpClient インスタンスがそれを拾います。コンテナ環境では「設定した覚えのないプロキシが、なぜか使われている」という混乱のもとになりがちです。
ステップ 1: 新しい C# コンソールプロジェクトを作る
ターミナルを開き、新規プロジェクトを用意します。
dotnet new console -n ProxyHttpClientDemo
cd ProxyHttpClientDemo
dotnet --version で SDK のバージョンを確かめておきましょう。本記事のサンプルは、機能をフルに使うため .NET 6 以上を前提にしています。最新の LTS SDK が必要なら、Microsoft のダウンロードページ から取得できます。
あとはエディタで Program.cs を開きます。ここが実装の中心になります。
ステップ 2: まずはプロキシなしで HTTP リクエストを送る
プロキシを仕込む前に、いまの外向き IP を控えておきます。そうしておけば、プロキシを有効にしたあとで本当に IP が変わったかを確認できます。
using System.Net.Http;
using var client = new HttpClient();
var ip = await client.GetStringAsync("https://api.ipify.org/");
Console.WriteLine($"Direct IP: {ip}");
実行してみてください。いまの公開 IP が、たとえばこんなふうに表示されます。
Direct IP: 203.0.113.10
この値は覚えておきましょう。次のステップでは、別の値に変わっているはずです。
ステップ 3: HttpClientHandler に WebProxy を設定する
基本の組み合わせは、WebProxy・handler・client の3点セットです。
using System.Net;
using System.Net.Http;
var proxy = new WebProxy("http://proxy.example.com:8080")
{
BypassProxyOnLocal = false
};
var handler = new HttpClientHandler
{
Proxy = proxy,
UseProxy = true,
UseDefaultCredentials = false
};
using var client = new HttpClient(handler);
var ip = await client.GetStringAsync("https://api.ipify.org/");
Console.WriteLine($"Proxy IP: {ip}");
proxy.example.com:8080 は、実際のプロキシエンドポイントに置き換えてください。正しく設定できていれば、表示される IP はあなた本来の IP ではなく、プロキシの出口 IP になります。
押さえておきたい主なプロパティは、次のとおりです。
Proxy— ルーティングに使うIWebProxyインスタンスです。UseProxy = true— 実際にプロキシを使うよう handler に伝えます。うっかり忘れると、かなりの時間を溶かします。BypassProxyOnLocal = false— “ローカルっぽい” 宛先だけプロキシを素通りさせる挙動を抑えます。UseDefaultCredentials— Windows の既定資格情報を送るかどうかを決めます。プロキシのユーザー名/パスワードとは別物です。

ステップ 4: NetworkCredential でプロキシ認証を加える
有料プロキシの多くは認証を求めてきます。正しいやり方は、WebProxy オブジェクトそのものに資格情報を持たせることです。
using System.Net;
using System.Net.Http;
var proxy = new WebProxy("http://proxy.example.com:8080")
{
Credentials = new NetworkCredential("proxy-user", "proxy-password")
};
var handler = new HttpClientHandler
{
Proxy = proxy,
UseProxy = true
};
using var client = new HttpClient(handler);
var ip = await client.GetStringAsync("https://api.ipify.org/");
Console.WriteLine($"Authenticated proxy IP: {ip}");
プロバイダーによっては、http://username:password@host:port のような URL 形式を案内してくることがあります。とはいえ .NET では、URI 文字列に埋め込むよりも NetworkCredential を使うほうが安全です。パスワードに特殊文字が混じっていてもエスケープの問題を避けやすく、URI と認証情報をきっちり切り分けられます。
いちばんよくある認証ミス、つまり 407 エラーの原因については、このあと専用のセクションでじっくり扱います。
ステップ 5: レスポンスデータを取得・保存する
IP を確かめるだけでなく、実際の用途ではレスポンスをきちんとさばきましょう。
using var response = await client.GetAsync("https://example.com/api/products");
if (!response.IsSuccessStatusCode)
{
Console.WriteLine($"Request failed: {(int)response.StatusCode} {response.ReasonPhrase}");
return;
}
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
スクレイピング用途では、プロキシ経由のリクエストはあくまで“運搬の層”でしかありません。実際には、その先で解析・正規化・重複排除・再試行をこなし、Excel や Google Sheets、データベースなどへ書き出す工程が待っています。Thunderbit のようなツールを使えば、抽出からエクスポートまでをまとめて自動化できます。たとえば Chrome 拡張機能 を使えば、構造化データの抽出や、Google Sheets・Excel・Airtable・Notion への無料エクスポートを、解析コードを一切書かずに実現できます。
抽出データを Excel、Sheets、Airtable、Notion に出力 Get Started Free
407 エラーの正体: プロキシ認証とサーバー認証の取り違え

このミスは、Stack Overflow のスレッドでも、Microsoft Q&A の投稿でも、そして正直に白状すれば私自身のコードでも、何度となく見てきました。
違いそのものは単純ですが、ついつい混同してしまいます。
- プロキシ認証 は、プロキシサーバーそのものに対して自分を名乗ります。
- サーバー認証 は、目的地のサーバーに対して自分を名乗ります。
HttpClientHandler では、この2つは別々のプロパティです。間違ったほうに資格情報を入れると、407 Proxy Authentication Required の最大の原因になります。
// ❌ 間違い — プロキシではなく、目的地サーバー向けの資格情報を設定している
handler.Credentials = new NetworkCredential("user", "pass");
// ✅ 正解 — 資格情報はプロキシオブジェクトそのものに設定する
handler.Proxy = new WebProxy("http://proxy:8080")
{
Credentials = new NetworkCredential("user", "pass")
};
HttpClientHandler.Credentials は目的地側に向けた設定です。一方、WebProxy.Credentials はプロキシ向けです。プロキシが 407 を返してくるなら、資格情報の置き場所はプロキシ側だと思ってください。
もう1つ、隠れた落とし穴があります。HttpClientHandler.PreAuthenticate は、目的地サーバーに対する事前認証の挙動を制御するもので、Proxy-Authorization ヘッダーを操作するものではありません。407 の対処策として使うのは見当違いなので、避けましょう。
C# の HttpClient でプロキシをローテーションする方法
これはフォーラムで本当に頻繁に飛んでくる質問です。最初に答えを聞くと、少しがっかりするかもしれません。稼働中の HttpClient インスタンスのプロキシは、後から変えられません。 プロキシは handler に紐づき、handler は生成された時点で固定されます。HttpClient 側に可変の Proxy プロパティは用意されていないのです。
ありがちな安直策として、リクエストのたびに new HttpClient(new HttpClientHandler { Proxy = ... }) を作り直す手がありますが、これは別の問題を呼び込みます。Microsoft も、リクエストごとに client を生成・破棄すると TCP ポートが枯渇しうる とはっきり警告しています。接続を閉じても、ポートはすぐには解放されないからです。

そこで、実運用に耐える3つのパターンを紹介します。
選択肢 1: IHttpClientFactory による名前付きクライアント
起動の時点でプロキシのセットが分かっているなら、名前付きクライアント がいちばんシンプルです。各クライアントに独自の handler 設定を持たせ、実行時に名前で呼び出します。
builder.Services.AddHttpClient("proxy-us")
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
Proxy = new WebProxy("http://us-proxy.example.com:8080")
{
Credentials = new NetworkCredential("user", "pass")
},
UseProxy = true
});
builder.Services.AddHttpClient("proxy-eu")
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
Proxy = new WebProxy("http://eu-proxy.example.com:8080")
{
Credentials = new NetworkCredential("user", "pass")
},
UseProxy = true
});
// リクエスト時:
var client = httpClientFactory.CreateClient("proxy-us");
handler の寿命は factory が面倒を見てくれるので、リクエストのたびに client を作るアンチパターンを踏まずに済みます。
選択肢 2: SocketsHttpHandler + PooledConnectionLifetime(.NET 6 以降)
新しい接続ごとに出口 IP を切り替えるプロキシゲートウェイの背後で、長寿命の client を回す場合は、PooledConnectionLifetime で一定時間ごとに接続を張り直せます。
var handler = new SocketsHttpHandler
{
Proxy = new WebProxy("http://rotating-gateway.example.com:8080")
{
Credentials = new NetworkCredential("user", "pass")
},
UseProxy = true,
PooledConnectionLifetime = TimeSpan.FromMinutes(5)
};
using var client = new HttpClient(handler);
これは、リクエストごとに Proxy オブジェクトを魔法のように差し替えるわけではありません。新しい TCP 接続ごとに別の出口 IP を割り当てるプロキシゲートウェイや、時間とともに別のエンドポイントを返す DNS ベースのプロキシプールと、相性のよいやり方です。
選択肢 3: 高度なプロキシ選択のためのカスタム DelegatingHandler
URL やペイロード、実行時のコンテキストに応じてプロキシを選び分けたいなら、カスタムのルーティング handler で各リクエストを判定し、適切な内部 handler パイプラインへ流せます。
public sealed class ProxyRoutingHandler : DelegatingHandler
{
private readonly IReadOnlyDictionary<string, HttpMessageInvoker> _clients;
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
var key = SelectProxyKey(request);
return _clients[key].SendAsync(request, cancellationToken);
}
}
これは上級者向けの設計です。スレッドセーフ性、破棄処理、handler の再利用、リトライの挙動、ログ出力まで、すべて自前で見る必要があります。最初の2つがどうしても合わないときだけ、検討するのがよいでしょう。
3つのアプローチを比べる
| アプローチ | 複雑さ | .NET バージョン | スレッドセーフ性 | オーバーヘッド |
|---|---|---|---|---|
| 名前付きクライアント(IHttpClientFactory) | 低 | .NET Core 2.1 以降 | 高い(設定が不変) | 低い |
| SocketsHttpHandler + PooledConnectionLifetime | 中 | .NET 6 以降 | 高い | 低い |
| カスタム DelegatingHandler | 高 | すべて | 実装次第 | 中 |
多くのチームにとっては、名前付きクライアントから入るのが正解です。安定したローテーション型ゲートウェイを使うなら PooledConnectionLifetime へ進み、プロキシの選択がリクエスト単位のメタデータに左右される場合にだけ、カスタムルーティングを視野に入れましょう。
プロキシプロトコルの選び方: HTTP、HTTPS、SOCKS5
プロキシにも“話す言語”の違いがあり、プロトコルを取り違えると、わかりにくいエラーに化けます。
HTTP プロキシ: HTTP リクエストを解釈します。HTTP ターゲットならそのまま転送できます。HTTPS ターゲットの場合は、クライアントが CONNECT リクエストでトンネルを張り、そのトンネル越しに TLS を目的地とネゴシエートします。もっともよく使われる方式です。
HTTPS 終端型プロキシ: プロキシが自前の TLS 証明書を提示し、上流へ再暗号化して中継します。企業の検査系の仕組みや、一部の管理型スクレイピング API でよく見かけます。クライアントがプロキシの証明書チェーンを信頼していないと、証明書検証エラーの引き金になります。
SOCKS5 プロキシ: HTTP に限らず、あらゆる TCP 通信に使えるトランスポート層のトンネルです。住宅用プロキシ事業者で広く採用されています。.NET 6 以降がネイティブ対応しています。
SOCKS5 の例はこちらです。
var handler = new SocketsHttpHandler
{
Proxy = new WebProxy("socks5://proxy.example.com:1080")
{
Credentials = new NetworkCredential("proxy-user", "proxy-password")
},
UseProxy = true
};
using var client = new HttpClient(handler);
var ip = await client.GetStringAsync("https://api.ipify.org/");
Console.WriteLine(ip);
SSL 証明書検証についての注意
HTTPS 終端型プロキシを使うと、RemoteCertificateNameMismatch エラーが出ることがあります。その場合は ServerCertificateCustomValidationCallback で検証の挙動をカスタマイズできます。
var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
};
これはローカル開発か、信頼済みで承認された TLS インターセプト型プロキシに限って使ってください。 むやみに true を返すと、重要なセキュリティチェックを無効化し、中間者攻撃の的になります。通常の CONNECT プロキシや SOCKS プロキシを本番で使うときは、SSL 検証を有効のままにしておきましょう。
C# の HttpClient でよくあるプロキシエラーを切り分ける

この表は、目に見える症状を、考えられる原因と最初に試すべき対処へと結びつけたものです。ぜひブックマークしておいてください。 Stack Overflow のスレッドや開発者フォーラムで頻出のエラーを拾い上げています。
| エラー / 症状 | よくある原因 | 対処法 |
|---|---|---|
| 407 Proxy Authentication Required | 資格情報を handler.Proxy.Credentials ではなく handler.Credentials に設定している; ユーザー名の形式が違う; URL 埋め込みパスワードに特殊文字がある | WebProxy.Credentials = new NetworkCredential(...) を使う; URI に資格情報を埋め込まない; プロバイダー指定のユーザー名形式を確認する |
| TaskCanceledException / Timeout | プロキシが遅い、到達不能、過負荷、またはファイアウォールで遮断されている; 既定 100 秒のタイムアウトでは短すぎる | まず curl でプロキシをテストする; エンドポイントが正常だと確認してから HttpClient.Timeout を延長する; リトライとプロキシヘルスチェックを追加する |
| SocketException / Socket exhaustion | リクエストごとに HttpClient または handler を生成・破棄している | IHttpClientFactory、シングルトン client、または pooling 制御 付きの SocketsHttpHandler を使う |
| SSL RemoteCertificateNameMismatch | 企業プロキシや管理型プロキシによる HTTPS 介入 | 必要に応じてプロキシ CA を信頼済みにする; 検証のカスタム設定は、管理された開発環境や許可済み MITM シナリオに限定する |
| 302 リダイレクトループ | 企業プロキシ/VPN のキャプティブページや allowlist ブロックが繰り返しリダイレクトしている | 直接接続を試す; Location ヘッダーを確認する; プロキシの allowlist と認証ポータルを確認する |
| HttpRequestException / SOCKS URL で接続できない | SOCKS コードを .NET Framework や古い .NET で実行している; スキームやポートが間違っている | ネイティブ SOCKS 対応には .NET 6 以上を使う; socks5://host:port を確認する; プロバイダーのドキュメントで検証する |
| プロキシが無視されているように見える | UseProxy = false; 宛先がローカル扱いでバイパスされている; NO_PROXY 環境変数; handler の設定が想定と違う | UseProxy = true にする; HttpClient.DefaultProxy を確認する; 環境変数を消すか上書きする; BypassProxyOnLocal = false にする |
手早いデバッグの段取り
- そもそもリクエストは成功したか。 → 成功しているなら、
api.ipify.orgの出力を、想定するプロキシ IP と突き合わせます。 - 失敗したが、HTTP ステータスコードは返ってきたか。 → 407 ならプロキシ認証を直します。403/429 なら、対象サイトがプロキシを弾くか絞っています。3xx ループなら、プロキシや企業ゲートウェイのリダイレクトが疑わしいです。
- ステータスコードはなく、例外だけが飛んでくるか。 → Timeout ならプロキシの到達性を確認。Socket や証明書まわりの例外なら、pooling・プロトコル・TLS・.NET バージョンを点検します。
.NET の外側でプロキシ自体を確かめるのに便利なコマンドはこちらです。
curl -x http://user:pass@proxy.example.com:8080 https://api.ipify.org/
curl --socks5 user:pass@proxy.example.com:1080 https://api.ipify.org/
curl では通るのに C# では通らない場合、たいていの違いは認証方式、TLS の信頼ストア、環境変数、あるいは資格情報のエスケープにあります。まずは curl のプロキシ URL・スキーム・認証方式を正確にそろえ、その上で資格情報を NetworkCredential に移しましょう。
プロキシ管理から手を引くべきとき: ノーコードという選択肢
「HttpClient proxy C#」で検索する開発者の多くは、プロキシの理論を学びたいわけではなく、スクレイパーを止めずに動かしたいだけです。だからこそ、カスタムの C# プロキシコードが本当に要る場面と、そうでない場面を、正直に見極めておく価値があります。
次のような場合は、プロキシローテーション付きの C# スクレイパーを自前で組むべきです:
- リクエストロジック、Cookie、ヘッダー、リトライ、解析を、細かく握っておきたい
- 既存の .NET コードベースや社内サービスに組み込みたい
- コンプライアンスやセキュリティの要請から、インフラをエンドツーエンドで自前で抱える必要がある
次のような場合は、Thunderbit のようなノーコードツールが向いています:
- 目的は HTTP インフラそのものではなく、Web サイトからの構造化データ抽出だ
- プロキシプールの管理や CAPTCHA 対応、ソケット枯渇のデバッグに時間を取られたくない
- チームが Excel、Google Sheets、Airtable、Notion に、解析コードなしでデータを欲しがっている
Thunderbit の Chrome 拡張は、クラウドスクレイピングのオプションを通じて、プロキシローテーションやボット対策を自動でさばきます。API では JSON スキーマを定義するだけで、HttpClient や WebProxy をまったく触らずに構造化データを受け取れます。価格比較のための Web スクレイピングやリード抽出に取り組むチームなら、セットアップ時間の差はかなり効いてくるはずです。
| シナリオ | カスタム C# + プロキシ | Thunderbit |
|---|---|---|
| リクエストロジックの完全制御 | あり | なし(API レベルの制御) |
| プロキシ管理が必要 | あり | なし(自動処理) |
| ボット対策 / CAPTCHA 対応 | 手動または外部サービス | 標準搭載 |
| セットアップ時間 | 数時間〜数日 | 数分 |
| 最適な用途 | 既存の .NET コードベース、カスタムパイプライン | 迅速なデータ抽出、非技術チーム、スプレッドシート出力 |
念のため言えば、「HttpClient を絶対に使うな」という話ではありません。本番の .NET サービスを作るなら、プロキシ設定はきちんと理解しておくべきです。ただ、単発のデータ収集のために 407 エラーのデバッグへ何時間も注いでいるなら、もっと手軽な選択肢もありますし、それを選ぶのは少しも恥ずかしいことではありません。Thunderbit の料金を確かめるか、YouTube チャンネルで実際の使い方をのぞいてみてください。
押さえどころ
おおもとの流れは変わりません。WebProxy → handler → HttpClient。その先は、本番で起きがちな運用ミスをいかに避けるか、という話に尽きます。
- 資格情報は handler ではなく、プロキシに設定する。 407 セクションの対比が、いちばん大事な勘どころです。
- リクエストごと・プロキシごとに新しい
HttpClientを作らない。 名前付きクライアントならIHttpClientFactory、ローテーション型ゲートウェイならPooledConnectionLifetime付きのSocketsHttpHandler、込み入ったケースではカスタムルーティング handler を使い分けましょう。 - SOCKS5 や
SocketsHttpHandlerのコードを貼る前に、.NET バージョンを確認する。 上の互換性表が、静かな失敗を防いでくれます。 - まず .NET の外側でプロキシを試す。 とりあえず
curlを叩くだけで、デバッグの対象が一気に絞れます。 - プロキシに振り回されたくない構造化データ抽出には、 Thunderbit のようなツールを使えば、通信層を任せてデータそのものに集中できます。
次に 407 や TaskCanceledException にぶつかったら、まずは上のトラブルシューティング表から見直してみてください。
FAQ
既存の HttpClient インスタンスのプロキシを変更できますか?
できません。プロキシは handler に紐づき、handler は生成された時点で固定されます。HttpClient に可変の Proxy プロパティはありません。別のプロキシを使いたいなら、handler と client をそれぞれ別に用意し、IHttpClientFactory の名前付きクライアントか、設定済み client のプールで束ねて管理してください。
HttpClient は既定でシステムプロキシを使いますか?
使います。モダン .NET では、handler を明示的に設定しないと、HttpClient はシステムの既定プロキシ設定を引き継ぎます。HTTPS_PROXY や HTTP_PROXY のような環境変数も HttpClient.DefaultProxy 経由で効いてきます。使いたくない場合は、handler で UseProxy = false を明示してください。
C# の HttpClient で SOCKS5 プロキシを使うには?
SocketsHttpHandler と new WebProxy("socks5://host:port") を組み合わせます。ネイティブの SOCKS プロキシ対応には .NET 6 以降が必要です。.NET Framework 4.x では SOCKS5 を標準では扱えないため、サードパーティ製ライブラリが要ります。
407 Proxy Authentication Required が何度も出るのはなぜ?
ほとんどの場合、資格情報を handler.Proxy.Credentials ではなく handler.Credentials に置いているのが原因です。handler.Credentials は目的地サーバー向け、handler.Proxy.Credentials はプロキシ向けです。正しい設定は、上の「プロキシ認証とサーバー認証の違い」のセクションを参照してください。
プロキシ利用時に SSL 証明書検証を無効にしても安全ですか?
ローカル開発か、プロキシ提供元を全面的に信頼できる場合に限られます。たとえば、HTTPS プロキシモードの管理型スクレイピング API などです。標準の CONNECT プロキシや SOCKS プロキシを本番で使うなら、中間者攻撃を防ぐために SSL 検証は有効のままにしておいてください。
手間いらずで Web スクレイピングを始めるなら Thunderbit を試す Get Started Free
さらに詳しく知る


