PuppeteerSharp proxy: proxy cho trình duyệt, context và xác thực
PuppeteerSharp proxy là cách cho thư viện PuppeteerSharp của .NET điều khiển Chrome hoặc Edge đi qua máy trung gian. PuppeteerSharp có hai mức đặt proxy: cờ khởi động cho cả trình duyệt, và ProxyServer cho từng BrowserContext. Tài khoản proxy đặt bằng AuthenticateAsync. ProxyVN đối chiếu tài liệu PuppeteerSharp 25.15.0 và kiểm cơ chế proxy theo context trên Edge thật.
PuppeteerSharp proxy là bản .NET của Puppeteer
Cùng cơ chế, khác ngôn ngữ
PuppeteerSharp do Darío Kondratiuk duy trì, là bản chuyển Puppeteer của Node.js sang .NET. Trang PuppeteerSharp mô tả API bám sát Puppeteer gốc với tên phương thức theo quy ước C#: LaunchAsync, NewPageAsync, GoToAsync, AuthenticateAsync. Bên dưới, cả hai đều điều khiển trình duyệt qua Chrome DevTools Protocol.
Vì cùng cơ chế, mọi quy tắc proxy của Chromium áp dụng nguyên vẹn. Cờ --proxy-server không mang được tài khoản, xác thực phải đi qua CDP. Bài cách sử dụng proxy trong Puppeteer nói về bản Node, bài này chỉ đi vào API C# và những điểm khác do .NET.
Kinh nghiệm proxy với Puppeteer Node chuyển được sang PuppeteerSharp, nhưng tên phương thức và cách xử lý bất đồng bộ thì khác. Đừng chép nguyên mã JavaScript rồi dịch từng dòng.
Phạm vi kiểm thử
Máy lab hôm viết bài không có .NET SDK, nên chương trình PuppeteerSharp chưa được biên dịch và chạy. Mình đọc tài liệu API trên trang chính thức, bản mới nhất trên NuGet là 25.15.0 ngày 27/10/2026. Phần proxy theo context được kiểm bằng cách gửi đúng lệnh CDP mà BrowserContextOptions dùng tới Edge 156 thật.
Lab dùng hai proxy mở không cần tài khoản ở hai cổng khác nhau, mỗi proxy ghi nhật ký riêng, và một proxy cần tài khoản user1 với mật khẩu p@ss#2026. Website thử tên shop.test chỉ phân giải được bên trong proxy.
Cài đặt và đặt PuppeteerSharp proxy cho cả trình duyệt

Proxy cho cả trình duyệt
Project và gói
Tạo ứng dụng console .NET, thêm gói PuppeteerSharp trên NuGet với phiên bản ghim. PuppeteerSharp có thể tải trình duyệt về bằng BrowserFetcher, hoặc dùng trình duyệt có sẵn qua ExecutablePath.
dotnet new console -n PuppeteerProxyLab
cd PuppeteerProxyLab
dotnet add package PuppeteerSharp --version 25.15.0
Trên máy chủ sau proxy công ty, bước BrowserFetcher tải trình duyệt cũng cần ra Internet và có cơ chế mạng riêng. Dùng ExecutablePath trỏ tới Chrome hoặc Edge đã cài sẵn để không phụ thuộc bước tải lúc chạy.
--proxy-server trong Args
LaunchOptions có thuộc tính Args nhận mảng cờ dòng lệnh truyền cho trình duyệt. Proxy cho cả trình duyệt đặt bằng cờ --proxy-server.
using PuppeteerSharp;
var options = new LaunchOptions
{
Headless = true,
ExecutablePath = @"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe",
Args = new[] { "--proxy-server=http://203.0.113.10:8080" }
};
await using var browser = await Puppeteer.LaunchAsync(options);
await using var page = await browser.NewPageAsync();
await page.GoToAsync("http://httpbin.org/ip");
Console.WriteLine(await page.EvaluateExpressionAsync<string>("document.body.innerText"));
Cờ này áp cho mọi tab và mọi context không có proxy riêng. Giá trị chỉ gồm giao thức, máy và cổng, không có tài khoản. Bài định dạng proxy giải thích cách tách ip:port:user:pass thành phần địa chỉ và phần tài khoản.
Danh sách bỏ qua
Cờ --proxy-bypass-list nhận danh sách host đi thẳng, cách nhau bằng dấu chấm phẩy. Mặc định Chromium bỏ qua proxy cho localhost. Muốn buộc cả địa chỉ cục bộ đi qua proxy, như khi kiểm bằng proxy cục bộ có nhật ký, đặt giá trị <-loopback>.
Bài no_proxy là gì giải thích ý tưởng chung của danh sách bỏ qua. Với Chromium, cú pháp là của Chromium chứ không phải biến NO_PROXY.
PuppeteerSharp proxy theo BrowserContext
BrowserContextOptions.ProxyServer
Tài liệu lớp BrowserContextOptions có ba thuộc tính: DownloadBehavior, ProxyBypassList và ProxyServer. Mô tả của ProxyServer ghi đó là máy chủ proxy kèm cổng tùy chọn dùng cho mọi request của context, tên và mật khẩu đặt bằng AuthenticateAsync. ProxyBypassList là danh sách host bỏ qua proxy.
await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });
var ctxA = await browser.CreateBrowserContextAsync(new BrowserContextOptions
{
ProxyServer = "http://127.0.0.1:8932",
ProxyBypassList = new[] { "<-loopback>" }
});
var ctxB = await browser.CreateBrowserContextAsync(new BrowserContextOptions
{
ProxyServer = "http://127.0.0.1:8962",
ProxyBypassList = new[] { "<-loopback>" }
});
var pageA = await ctxA.NewPageAsync();
var pageB = await ctxB.NewPageAsync();
await pageA.GoToAsync("http://shop.test:8931/ctx-A");
await pageB.GoToAsync("http://shop.test:8961/ctx-B");
Đây là cách chạy nhiều proxy trong một tiến trình trình duyệt, tiết kiệm bộ nhớ hơn khởi chạy nhiều trình duyệt. Mỗi context có cookie, bộ nhớ đệm và proxy riêng.
Kiểm thật trên Edge
BrowserContextOptions dựa trên lệnh CDP Target.createBrowserContext với tham số proxyServer và proxyBypassList. Mình gửi đúng lệnh này tới Edge 156 không giao diện: tạo context A với proxy cổng 8932, context B với proxy cổng 8962, rồi mở ctx-A trong context A và ctx-B trong context B.
Nhật ký của proxy cổng 8932 chỉ có request tới ctx-A. Nhật ký của proxy cổng 8962 chỉ có request tới ctx-B. Không có request nào lẫn sang proxy kia. Proxy theo context hoạt động độc lập trên Edge, đúng như mô tả của BrowserContextOptions.
Lưu lượng nền đi đâu
Trong các lần chạy trước với --proxy-server cho cả trình duyệt, nhật ký proxy ghi nhiều kết nối nền của Edge tới edge.microsoft.com, config.edge.skype.com, www.bing.com, ntp.msn.com và nav-edge.smartscreen.microsoft.com. Với proxy theo context và không đặt --proxy-server, nhật ký của hai proxy context chỉ có request của trang.
Lưu lượng nền của trình duyệt đi theo cấu hình mạng mặc định, tức không qua proxy của context. Điều này có lợi: băng thông proxy dành cho trang, website đích không thấy các request lạ của trình duyệt đi qua IP proxy. Nhưng nó cũng nghĩa là trình duyệt vẫn tự ra Internet bằng IP của máy, cần tính tới nếu máy chủ không được phép ra ngoài trực tiếp.
Xác thực PuppeteerSharp proxy bằng AuthenticateAsync
Credentials và AuthenticateAsync

Tài khoản qua AuthenticateAsync
Lớp Credentials có hai thuộc tính Username và Password, dùng cho phương thức AuthenticateAsync của trang. Tên và mật khẩu là chuỗi riêng, không nằm trong URL, nên không cần mã hóa phần trăm cho ký tự đặc biệt.
var page = await ctxA.NewPageAsync();
await page.AuthenticateAsync(new Credentials
{
Username = Environment.GetEnvironmentVariable("PROXY_USER"),
Password = Environment.GetEnvironmentVariable("PROXY_PASS")
});
await page.GoToAsync("https://example.com/");
Gọi AuthenticateAsync trước GoToAsync. Bên dưới, phương thức bật domain Fetch của CDP với xử lý thử thách xác thực, giống cơ chế HandleAuth của Rod mà mình đã mô phỏng trong bài Rod.
Hành vi trình duyệt khi nhận tài khoản qua CDP
Mình đã mô phỏng cơ chế Fetch trên Edge với proxy cần mật khẩu. Request đầu tiên của trang bị proxy trả 407, trình duyệt phát sự kiện yêu cầu xác thực, CDP trả tài khoản. Request tiếp theo có tiêu đề Proxy-Authorization. Các trang mở sau trong cùng phiên trình duyệt gửi tài khoản ngay từ đầu.
Với PuppeteerSharp, AuthenticateAsync gắn với từng trang. Mỗi trang mới trong context có proxy cần mật khẩu nên gọi AuthenticateAsync, kể cả khi trình duyệt có thể đã nhớ tài khoản. Gọi rõ ràng cho mỗi trang giúp mã không phụ thuộc vào hành vi nhớ tài khoản vốn có thể khác giữa các bản trình duyệt.
Kết hợp với chặn bắt request
AuthenticateAsync và SetRequestInterceptionAsync cùng dùng Fetch của CDP. Khi bật chặn bắt request để chặn ảnh hay sửa tiêu đề, mọi request phải được cho đi tiếp hoặc hủy trong trình xử lý sự kiện Request, nếu không trang treo. Thử kỹ hai tính năng cùng nhau trên proxy có nhật ký.
Với PuppeteerSharp proxy, địa chỉ proxy nằm ở cờ khởi động hoặc BrowserContextOptions, còn tài khoản luôn đi qua AuthenticateAsync. Không có chỗ nào nhận user:pass trong URL proxy.
Nhiều phiên với PuppeteerSharp proxy
Một context cho một phiên

Mỗi context một proxy
Với tác vụ cần nhiều IP, ví dụ kiểm hiển thị quảng cáo ở nhiều vùng hay so giá giữa các thị trường, tạo một context cho mỗi proxy và đặt tên context theo vùng để dễ đọc log. Mỗi context có cookie riêng, nên phiên đăng nhập ở context này không lộ sang context khác. Khi xong việc, đóng context bằng CloseAsync để giải phóng bộ nhớ và kết nối tới proxy của context đó.
Với proxy xoay đổi IP theo tên người dùng, mỗi context dùng một mã phiên trong Username của AuthenticateAsync. Đóng context và tạo context mới khi cần IP mới. Cách này nhẹ hơn khởi chạy lại cả trình duyệt.
Giới hạn của proxy theo context
Proxy theo context hoạt động với HTTP và HTTPS qua proxy HTTP. Với proxy SOCKS5, Chromium hỗ trợ cú pháp socks5:// trong proxyServer nhưng không hỗ trợ SOCKS5 có tài khoản, và AuthenticateAsync chỉ xử lý thử thách xác thực HTTP. SOCKS5 có mật khẩu vì vậy không dùng được trực tiếp, cần proxy xác thực theo IP hoặc cổng HTTP.
Mỗi context dùng chung tiến trình trình duyệt. Một trang treo hay ngốn bộ nhớ ở context này ảnh hưởng tới các context khác. Với số context lớn, chia ra nhiều trình duyệt, mỗi trình duyệt vài chục context, và theo dõi bộ nhớ.
Thư mục dữ liệu
Context tạo bằng CreateBrowserContextAsync là context không lưu trạng thái lên đĩa, đóng là mất cookie. Nếu cần giữ phiên đăng nhập giữa các lần chạy, dùng UserDataDir của LaunchOptions cho context mặc định, mỗi proxy một thư mục. Không dùng chung UserDataDir giữa các proxy.
Timeout, lỗi và ngoại lệ trong PuppeteerSharp proxy
Timeout của GoToAsync
GoToAsync nhận tùy chọn điều hướng có Timeout tính bằng mili giây và WaitUntil cho điều kiện tải xong. Qua proxy, trang chậm hơn đi thẳng vì mỗi tài nguyên đi thêm một chặng. Điều kiện chờ mạng yên với proxy dân cư có thể mất lâu, cân nhắc chờ DOMContentLoaded hoặc chờ phần tử cụ thể bằng WaitForSelectorAsync.
Khi hết giờ, PuppeteerSharp ném ngoại lệ timeout. Bắt riêng ngoại lệ này để phân biệt trang chậm với lỗi kết nối proxy.
Lỗi điều hướng do proxy
Khi proxy không mở cổng hoặc từ chối, trình duyệt báo lỗi điều hướng với mã lỗi mạng của Chromium, ví dụ net::ERR_PROXY_CONNECTION_FAILED hay net::ERR_TUNNEL_CONNECTION_FAILED. PuppeteerSharp chuyển thành ngoại lệ điều hướng chứa mã đó. Đọc mã lỗi trong thông điệp để biết lỗi ở proxy hay ở website.
Thông điệp hoặc hiện tượng |
Thường do |
Kiểm trước |
|---|---|---|
net::ERR_PROXY_CONNECTION_FAILED |
Proxy không mở cổng hoặc sai địa chỉ |
ProxyServer, cờ --proxy-server |
net::ERR_TUNNEL_CONNECTION_FAILED |
Proxy từ chối mở đường hầm HTTPS |
Tài khoản, quyền CONNECT |
Trang trả 407 hoặc dừng tải |
Thiếu AuthenticateAsync |
Gọi trước GoToAsync |
Trang vẫn ra IP máy |
Context không có ProxyServer, không có cờ |
Cấu hình context |
Ngoại lệ timeout |
Proxy chậm, điều kiện chờ quá chặt |
Timeout, WaitUntil |
localhost không qua proxy |
Chromium bỏ qua loopback |
ProxyBypassList <-loopback> |
Các mã lỗi Chromium trong bảng là mã chung của trình duyệt, đã có hướng dẫn chi tiết ở bài lỗi ERR_TUNNEL_CONNECTION_FAILED. Khi gặp 407, bài sửa lỗi 407 Proxy Authentication Required liệt kê nguyên nhân phía nhà cung cấp.
Không bỏ qua lỗi chứng chỉ
LaunchOptions có AcceptInsecureCerts để chấp nhận chứng chỉ không hợp lệ. Với proxy HTTP thông thường kiểu CONNECT, không cần và không nên bật. Chỉ bật trong lab khi dùng công cụ giải mã HTTPS để quan sát lưu lượng, không bao giờ trên hệ thống thật.
PuppeteerSharp proxy trong ứng dụng ASP.NET và dịch vụ nền
Một trình duyệt dùng chung
Khởi chạy trình duyệt tốn vài giây và vài trăm megabyte bộ nhớ. Trong ứng dụng web hay dịch vụ nền, khởi chạy một trình duyệt khi ứng dụng bắt đầu, giữ suốt vòng đời, và tạo context cho từng tác vụ. Đăng ký dịch vụ quản lý trình duyệt dưới dạng singleton trong DI, đóng trình duyệt khi ứng dụng dừng.
Với proxy theo context, mỗi tác vụ xin một context với proxy phù hợp, làm xong thì đóng context. Trình duyệt dùng chung không bị ảnh hưởng bởi proxy của từng tác vụ, vì proxy nằm ở context.
Giới hạn số tác vụ đồng thời
Mỗi context và mỗi trang đều tốn bộ nhớ. Dùng SemaphoreSlim giới hạn số tác vụ chạy cùng lúc, đặt bằng mức mà máy chủ chịu được và không vượt hạn mức kết nối của gói proxy. Khi semaphore đầy, tác vụ mới chờ thay vì mở thêm context.
Với nhiều proxy dùng chung một tài khoản, cộng số context đang dùng tài khoản đó lại để so với hạn mức của gói. Vượt hạn mức, proxy có thể từ chối, trong log trông như lỗi điều hướng ngẫu nhiên.
Phục hồi khi trình duyệt chết
Trình duyệt có thể chết vì hết bộ nhớ hay lỗi trang. Dịch vụ quản lý nên phát hiện sự kiện ngắt kết nối của trình duyệt, khởi chạy lại, và để các tác vụ đang chạy thất bại rõ ràng thay vì treo. Sau khi khởi chạy lại, các context cũ không còn, tác vụ phải tạo context mới với proxy của mình.
PuppeteerSharp proxy với Firefox
Hỗ trợ Firefox khác Chromium
LaunchOptions có thuộc tính Browser để chọn Chrome hoặc Firefox, và ExtraPrefsFirefox cho tùy chọn riêng của Firefox. Firefox không dùng cờ --proxy-server của Chromium. Cấu hình proxy của Firefox nằm trong các tùy chọn network.proxy của hồ sơ trình duyệt.
Mình chưa thử Firefox trong lab, và không khẳng định BrowserContextOptions.ProxyServer hoạt động với Firefox như với Chromium. Nếu dự án cần Firefox, kiểm từng tính năng proxy trên Firefox bằng proxy có nhật ký trước khi dùng.
Khi nào cần Firefox
Firefox hữu ích khi kiểm hiển thị trang trên nhiều trình duyệt hoặc khi website đối xử khác với Chromium. Với phần lớn tác vụ lấy dữ liệu, Chromium với proxy theo context đủ dùng và đã được kiểm trong bài.
Hiệu năng của PuppeteerSharp proxy
Chặn tài nguyên không cần
Trang hiện đại tải hàng trăm tài nguyên. Qua proxy, mỗi tài nguyên đi thêm một chặng và tốn băng thông. Bật SetRequestInterceptionAsync, chặn ảnh, font, video khi chỉ cần văn bản, cho các request khác đi tiếp. Nhật ký proxy trước và sau khi chặn cho thấy số request giảm bao nhiêu.
Nhớ rằng chặn bắt request và AuthenticateAsync cùng dùng Fetch. Trong trình xử lý sự kiện Request, mọi request phải được gọi ContinueAsync hoặc AbortAsync, kể cả request mình không quan tâm, nếu không trang treo chờ.
Chọn điều kiện chờ phù hợp
GoToAsync với điều kiện chờ mạng yên đợi tới khi không còn request trong một khoảng thời gian. Qua proxy chậm, điều kiện này có thể không bao giờ đạt với trang có kết nối dài. Chờ DOMContentLoaded rồi WaitForSelectorAsync cho phần tử cần lấy thường nhanh và ổn định hơn.
Đo thời gian từ GoToAsync tới khi có dữ liệu, so giữa đi thẳng và qua proxy, giữa các proxy với nhau. Số liệu này giúp chọn proxy gần website đích và đặt timeout hợp lý.
Chuyển mã Puppeteer Node sang PuppeteerSharp proxy
Ánh xạ khái niệm
Với Puppeteer Node, proxy đặt bằng args trong puppeteer.launch và tài khoản bằng page.authenticate. Với PuppeteerSharp, tương ứng là Args trong LaunchOptions và AuthenticateAsync. Proxy theo context ở Node dùng tùy chọn proxyServer của browser.createBrowserContext, ở PuppeteerSharp dùng BrowserContextOptions.ProxyServer.
Khác biệt lớn nhất là bất đồng bộ. Mọi lời gọi trong PuppeteerSharp trả Task và cần await. Quên await một AuthenticateAsync có thể làm GoToAsync chạy trước khi xác thực được bật, trang lỗi 407 một cách không nhất quán. Bật cảnh báo trình biên dịch cho Task không được await để bắt lỗi này.
Giải phóng tài nguyên
Browser, BrowserContext và Page trong PuppeteerSharp triển khai IAsyncDisposable. Dùng await using để chắc chúng được đóng khi ra khỏi phạm vi. Quên đóng context khi dùng proxy theo context để lại kết nối mở tới proxy và tiêu tốn hạn mức.
Kiểm PuppeteerSharp proxy bằng nhật ký
Proxy có nhật ký
Cách chắc nhất để biết trang đi đường nào là cho nó qua proxy ghi nhật ký, như hai proxy cổng 8932 và 8962 trong lab. Với hai context dùng hai proxy, mỗi nhật ký chỉ được có request của context tương ứng. Thấy request lẫn sang là cấu hình sai.
Bộ ca kiểm tối thiểu
- Không proxy: trang tới tên chỉ có trong proxy báo lỗi phân giải.
- --proxy-server cho cả trình duyệt: trang qua proxy, nhật ký có thêm lưu lượng nền của trình duyệt.
- Hai context hai proxy: mỗi nhật ký chỉ có request của context mình.
- Context có proxy cần mật khẩu, không AuthenticateAsync: trang lỗi, nhật ký ghi 407.
- Có AuthenticateAsync: trang mở, nhật ký có tài khoản.
- Proxy chết: ngoại lệ có net::ERR_PROXY_CONNECTION_FAILED.
- Kiểm IP ra cho từng context: mỗi context ra đúng IP proxy của nó.
Ca thứ ba là ca quan trọng nhất khi dùng proxy theo context, vì lỗi lẫn proxy giữa các context không báo ngoại lệ nào.
Đọc kết quả kiểm theo từng context
Khi chạy bộ ca kiểm với nhiều context, so số dòng trong nhật ký của từng proxy với số trang mà context tương ứng đã mở. Số dòng nhiều hơn số trang là bình thường vì mỗi trang tải nhiều tài nguyên. Số dòng bằng không trong khi context đã mở trang là dấu hiệu context không dùng proxy đó, có thể do quên ProxyServer hoặc trang lỗi trước khi gửi request.
Nếu thấy request của context này xuất hiện trong nhật ký proxy của context khác, dừng ngay và kiểm mã tạo context. Lỗi này thường do dùng lại một biến BrowserContextOptions đã sửa giữa hai lần tạo context, hoặc mở trang bằng trình duyệt thay vì bằng context. Gọi NewPageAsync trên đối tượng browser tạo trang trong context mặc định, không phải context có proxy. Đây là lỗi dễ mắc nhất khi chuyển mã từ một proxy cho cả trình duyệt sang proxy theo context, vì mã cũ quen gọi browser.NewPageAsync ở mọi nơi.
Ghi log theo context
Ghi mỗi lần điều hướng kèm định danh context, proxy dùng, URL, thời gian và kết quả, cùng mã lỗi net::ERR nếu có. Không ghi mật khẩu. Khi một vùng có kết quả bất thường, log cho biết context nào, proxy nào, để kiểm lại đúng chỗ.
PuppeteerSharp proxy trong container Linux
Trình duyệt trong ảnh container
Chạy PuppeteerSharp trong container Linux cần một trình duyệt và các thư viện hệ thống mà trình duyệt phụ thuộc. Cài Chrome hoặc Chromium vào ảnh ở bước dựng, đặt ExecutablePath trỏ tới nó. Không để BrowserFetcher tải trình duyệt lúc chạy, vì container sau proxy có thể không tải được và mỗi lần khởi động lại tốn thời gian.
Biến môi trường HTTP_PROXY của container không tự áp cho trình duyệt. Đọc giá trị từ cấu hình rồi truyền vào Args hoặc BrowserContextOptions. Ghi rõ trong tài liệu ảnh container rằng proxy của trình duyệt được cấu hình ở mã ứng dụng, không ở biến môi trường.
Chứng chỉ và proxy công ty
Sau proxy kiểm tra TLS của công ty, Chromium trên Linux dùng kho chứng chỉ NSS hoặc kho của hệ thống tùy cách dựng. Thêm CA nội bộ vào kho phù hợp ở bước dựng ảnh. Kiểm bằng cách mở một trang HTTPS qua proxy công ty từ container, xem có lỗi chứng chỉ không.
Không chữa lỗi chứng chỉ bằng AcceptInsecureCerts hay cờ bỏ qua lỗi chứng chỉ. Trình duyệt trong container thường chạy với dữ liệu đăng nhập của dịch vụ, chấp nhận chứng chỉ bất kỳ là rủi ro lớn.
Tài nguyên của container
Trình duyệt trong container cần bộ nhớ chia sẻ đủ lớn. Thiếu bộ nhớ chia sẻ, trang nặng có thể làm tab chết, trông như lỗi mạng hay lỗi proxy. Tăng kích thước bộ nhớ chia sẻ của container hoặc dùng cờ trình duyệt phù hợp. Khi thấy lỗi ngẫu nhiên chỉ trong container mà máy lập trình không có, kiểm bộ nhớ trước khi nghi proxy.
Bảo mật khi dùng PuppeteerSharp proxy
Tài khoản proxy không vào log
AuthenticateAsync nhận tài khoản dạng chuỗi trong bộ nhớ. Không ghi Credentials ra log, không đưa vào thông báo ngoại lệ tự tạo. Khi bật log chi tiết của PuppeteerSharp để gỡ lỗi CDP, kiểm xem lệnh Fetch.continueWithAuth có bị in kèm tài khoản không, và tắt log chi tiết trên hệ thống thật.
Tách dữ liệu giữa các khách hàng
Nếu dịch vụ chạy tác vụ cho nhiều khách hàng, mỗi khách hàng một context với proxy và cookie riêng. Không dùng chung context giữa khách hàng, kể cả khi dùng chung proxy. Đóng context ngay khi xong tác vụ để cookie và dữ liệu phiên không tồn tại lâu hơn cần thiết.
Đưa PuppeteerSharp proxy vào dự án thật
Gom cấu hình
Viết một dịch vụ quản lý trình duyệt: khởi chạy một trình duyệt dùng chung, cung cấp phương thức tạo context theo proxy, gọi AuthenticateAsync cho mỗi trang mới. Mã nghiệp vụ chỉ xin một trang cho một proxy, không tự dựng LaunchOptions hay BrowserContextOptions.
Đọc địa chỉ và tài khoản proxy từ cấu hình ứng dụng hoặc kho bí mật. Với ứng dụng ASP.NET, dùng user secrets khi phát triển và kho bí mật của nền tảng khi triển khai.
Chọn loại proxy
Vì tài khoản đi qua AuthenticateAsync, PuppeteerSharp dùng tốt proxy HTTP có mật khẩu. Proxy theo context cho phép nhiều IP trong một trình duyệt, hợp với kiểm hiển thị theo vùng hay kiểm giá nhiều thị trường. Với luồng có đăng nhập, chọn proxy tĩnh để giữ IP suốt phiên.
ProxyVN có proxy dân cư tĩnh, datacenter và proxy xoay, hỗ trợ HTTP và SOCKS5, cấp tài khoản user và mật khẩu. Nếu cần proxy cho các context PuppeteerSharp, anh em có thể mua proxy uy tín tại trang chủ ProxyVN rồi chạy bộ ca kiểm ở trên.
Tôn trọng website
Proxy chỉ đổi IP. Trình duyệt tự động vẫn có dấu hiệu nhận diện, tần suất cao vẫn bị giới hạn. Giãn nhịp điều hướng, tôn trọng điều khoản của website. Bài headless browser có thêm về đặc điểm trình duyệt không giao diện.
Câu hỏi thường gặp về PuppeteerSharp proxy
Đặt user:pass trong --proxy-server được không. Không. Chromium không nhận tài khoản trong cờ. Dùng AuthenticateAsync.
Có thể dùng nhiều proxy trong một trình duyệt không. Có, bằng BrowserContextOptions.ProxyServer cho từng context. Lab trên Edge cho thấy mỗi context đi đúng proxy của nó.
AuthenticateAsync gọi khi nào. Trên trang, trước GoToAsync. Gọi cho mỗi trang mới.
Lưu lượng nền của trình duyệt có đi qua proxy của context không. Trong lab thì không. Nó đi theo cấu hình mặc định của trình duyệt.
SOCKS5 có mật khẩu dùng được không. Không trực tiếp. Dùng proxy SOCKS5 xác thực theo IP hoặc cổng HTTP.
Có cần bật AcceptInsecureCerts không. Không với proxy HTTP thông thường.
Biến HTTP_PROXY có áp cho trình duyệt không. Không tự động. Truyền proxy qua Args hoặc BrowserContextOptions.
Có cần đóng context sau mỗi tác vụ không. Nên đóng, để giải phóng bộ nhớ, kết nối tới proxy và cookie của phiên.
Checklist PuppeteerSharp proxy

Checklist PuppeteerSharp proxy
Trước khi chạy thật
- ExecutablePath trỏ trình duyệt có sẵn trên máy chủ sau proxy.
- Địa chỉ proxy không kèm tài khoản.
- AuthenticateAsync cho mỗi trang khi proxy cần mật khẩu.
- Một context cho mỗi proxy, đóng context khi xong.
- ProxyBypassList đúng nhu cầu.
- Bắt ngoại lệ điều hướng và đọc mã net::ERR.
- Không bật AcceptInsecureCerts.
- Kiểm IP ra cho từng context.
Giới hạn của bài
Chương trình PuppeteerSharp chưa được biên dịch vì máy lab không có .NET SDK. Bài theo tài liệu API PuppeteerSharp và bản NuGet 25.15.0. Proxy theo context được kiểm bằng lệnh CDP Target.createBrowserContext trên Edge 156, cơ chế xác thực Fetch được kiểm ở bài Rod. Chưa thử Chrome, Firefox, SOCKS5 và gateway thương mại.
PuppeteerSharp proxy và những điều cần nhớ
PuppeteerSharp proxy đặt bằng --proxy-server cho cả trình duyệt hoặc BrowserContextOptions.ProxyServer cho từng context, tài khoản luôn qua AuthenticateAsync. Mỗi context đi đúng proxy của mình, lưu lượng nền không theo proxy context. Cần proxy ổn định cho PuppeteerSharp proxy, liên hệ Proxy.vn - Nhà cung cấp dịch vụ proxy chất lượng hàng đầu Việt Nam.