Browserless 本質上就是把 headless Chrome 打包成一個服務,讓你自己部署在主機上。它的 Docker 容器會持續跑著,透過 HTTP 或 WebSocket 接工作,並採用共享的接入限制,而不是讓每個呼叫端自己帶一份。以這裡的 REST 測試來看,服務在閒置時 完全沒有 Chrome 行程,只有在請求執行中才會建立 Chrome 行程,請求結束後又回到零。真正被池化的是服務容量和排隊機制,不是已驗證、先暖機好的瀏覽器行程集合。
我用 v2.55.0 搭配一個受控的本機 fixture 做了測試——把啟動拆成多個階段、在三種設定下驗證接入控制、用已知真值檢查端點準確性、做 30 個 session 的 soak 測試,還有 timeout 邊界測試。真正有用的結論比較偏營運層面,而不是速度提升:接入限制和客戶端看得到的回應一致,而那些尖銳問題大多都跟部署方式有關。
最有價值的結果不是延遲數字。Browserless 並沒有讓 Chrome 啟動更快——它只是替 Chrome 加了一套門禁:裡面同時固定放多少個 session,後面可以排多少個隊,其他人一律回 HTTP 429。當我改了兩個環境變數,這條上限就從 4 變成 8,再變成 10,而且容器自己的統計結果在每一次請求上都和我客戶端看到的狀態碼完全一致。
Browserless 到底是什麼
很多人會在這個分類上搞混。Browserless 不是你 import 進來就能直接呼叫的函式庫。它是一個 Docker 映像檔——ghcr.io/browserless/chromium——你把它當成長期運作的服務來跑。它負責代理瀏覽器工作,並提供兩種介面:REST 端點(/content、/scrape、/screenshot、/pdf,外加 /function 和 /unblock)以及可供 Puppeteer 和 Playwright connect() 的 CDP/WebSocket 介面。
我測的是 REST 介面。WebSocket 路徑確實存在,也被廣泛使用,但我沒有針對它做量測。
本次測試版本是 v2.55.0,檢查時間為 2026 年 7 月 27 日。
| 項目 | 數值 |
|---|---|
| 映像版本 | v2.55.0,發布於 2026 年 7 月 14 日 |
| Chrome | 149.0.7827.0 |
| Node | 24.18.0 |
| 基底映像 | Ubuntu 24.04 |
| GitHub stars | 截至 2026 年 7 月 27 日約 13,525 顆 |
星數會變動;請把它當成當下截面的數據。
授權門檻:SSPL-1.0 或商業授權
這個儲存庫提供的 Browserless 授權為 SSPL-1.0 或 Browserless 商業授權。在選擇路線之前,請先閱讀最新的 repository LICENSE 與 Browserless 的 官方開源部署指引。本文沒有針對商業產品、閉源應用、CI 系統、託管服務或內部部署做法律分析,因此不會替這些場景判定適用哪種授權。請由法務或負責軟體授權的人員評估你的部署與散佈模式。
Browserless 也有託管方案。價格與使用單位的定義變動很快,而且不屬於這次自架測試的範圍,所以請以官方網站為準,不要把這裡過時的表格當成採購證據。
session 模型在底層怎麼運作
我量到的 REST 路徑表現,像是每個請求各自處理一次瀏覽器工作;但這套測試環境並沒有深入追蹤 Browserless 內部機制,因此無法區分它到底是新開瀏覽器行程,還是用了某種可重用 context 的策略。能確認的事情比較單純:閒置時 Chrome 行程是 0;請求進行中時,會看到 11 個 Chrome 家族行程;順序執行結束後又回到 0。這個配置下,沒有任何證據顯示存在預熱過的瀏覽器池。
這個長駐的 Node 服務會接受有限數量的瀏覽器工作、再把另一批有限數量的工作排隊,剩下的直接拒絕。下面量到的架構契約,就是這種接入模型。不要因為看到「pool」這個詞,就推論行程或 context 一定能重用;這套 timing 測試無法證明那件事。
接入控制有兩個旋鈕:
CONCURRENT—— 同時跑幾個 session。QUEUED—— 額外可以排隊等候幾個請求。
容器的 /config 端點顯示預設值為 CONCURRENT=10、QUEUED=10、TIMEOUT=30000。超過 CONCURRENT + QUEUED 的部分會立刻被拒絕。
驗證不是可選項。Browserless v2 一律需要 token——如果你沒設定 TOKEN,它會在啟動時自動產生一組隨機 token 並印到 stdout。每個 REST 呼叫都要帶上 ?token=。
在可觀測性方面,你會拿到 /pressure(running、queued、CPU、memory、recently rejected)、/sessions 和 /config。另外也有一個 /metrics 的 JSON 匯出,但它需要設定 METRICS_JSON_PATH,而我這次沒有用到。映像檔則以 dumb-init 作為 PID 1,這也正是多年來容器化 Chrome 被抱怨殭屍行程問題時,官方所對應的做法。
安裝現實:一條指令,還有四件沒人會寫進那條指令的事
大家常引用的安裝方式,確實就是一條 docker run。但你真正需要規劃的,是它周邊的那些事。
這個映像檔有 4.34 GB。 這個數字才是你應該拿來預期的基準,而不是啟動延遲。這個 manifest 同時包含 linux/arm64 和 linux/amd64;在我的 arm64 主機上,Docker 下載的是原生 arm64 版本。(容器內 Chrome 的 user-agent 仍然會寫 X11; Linux x86_64——那只是 Chrome 在 Linux 上的外觀性 UA,不是模擬環境。uname -m 顯示的是 aarch64。很多人會為此提 bug。)
每次量測我都用了 --shm-size=2g。 測試環境沒有拿 Docker 預設的 /dev/shm 做對照組,所以本文不能說 2 GiB 在任何情況下都必須,也不能量化失敗點。你要依照瀏覽器數量與工作負載去設定大小。
token 是部署問題,不是形式主義。 沒有它,任何能路由到 3000 埠的人,都等於拿到了你網路裡的一個瀏覽器。
容器網路是你自己的責任。 我的 fixture 跑在主機上,所以容器透過 host.docker.internal 連過去(colima 會用 --add-host host.docker.internal:host-gateway 來映射)。在信任任何量測結果之前,我先用原始 curl 確認容器真的能打到 fixture。
我的環境是:colima 0.10.3(6 CPU / 11.6 GiB)搭配 macOS 26.5.2 arm64 上的 Docker 29.2.1。測試工具只用了 Python 3 標準函式庫。對 PNG 和 PDF,我只檢查檔案簽章,沒有驗證 decoder 正確性、尺寸、頁數、完整性或視覺一致性。
最小可用的啟動方式,會用到這裡鎖定的映像、明確的 token,以及這次使用的共享記憶體配置:
docker run --rm -p 3000:3000 --shm-size=2g \
-e TOKEN=replace-with-a-secret \
ghcr.io/browserless/chromium:v2.55.0
當 /pressure?token=... 有回應之後,帶 JSON body 且包含目標 URL 的已驗證 POST /content?token=... 就會走完整個 REST 路徑。正式環境的呼叫端也需要對 429 回應做有上限、帶 jitter 的重試;如果立刻重試,只會再次和同一個已滿的隊列競爭。
啟動成本:拆開來看

三次全新的 docker run 啟動,取中位數並附最小值到最大值:
| 階段 | 中位數 | 範圍 | 實際代表什麼 |
|---|---|---|---|
docker run → /pressure 回 200 | 0.78 秒 | 0.70–0.87 秒 | HTTP 端點已響應;這個檢查不能驗證瀏覽器是否已啟動 |
ready → 第一次 /content 渲染 | 0.32 秒 | 0.28–0.41 秒 | 觀察到的第一次請求:瀏覽器工作 + 載入頁面 + 回傳 HTML |
後續 /content 呼叫 | 0.15 秒 | 0.147–0.154 秒 | 同一容器中後續請求的延遲觀察值 |
中間那一列很容易被過度解讀。它沒有單獨量到瀏覽器啟動時間,也沒有證明 Browserless 比進程內函式庫啟動 Chrome 更快。 那是一次進到容器的 HTTP 往返,加上瀏覽器工作、導向與回應傳輸。首次與後續約 0.17 秒的差距,可能包含檔案系統、作業系統、Chrome、Node 或容器快取效應。由於閒置時 Chrome 行程為零,而且這些呼叫沒有捕捉 CDP trace 或行程時間線,所以不能把差距歸因於瀏覽器重用或「攤提後」的啟動成本。
另外要注意:這些是 macOS 上 colima VM 的數字。裸機 Linux 會不一樣。不要把 0.78 秒直接拿去跟你的 SRE 說,當成可移植的結論。
實作驗證:從兩邊看上限
CONCURRENT + QUEUED → 429 這個契約到處都有人提,但很少有人真的示範。
測法是:準備一個在伺服器端睡 5 秒的 fixture 路由,讓每個請求都能穩定地佔住一個 session 一段已知時間。接著同時丟出 CONCURRENT + QUEUED + 4 個請求,看會回什麼——同時再開一個 sampler thread 去輪詢 /pressure,讀取容器自己的統計。
| 設定 (CONCURRENT, QUEUED) | 發出請求數 | HTTP 200 | HTTP 429 | 伺服器 /pressure 峰值 (running / queued / recentlyRejected) |
|---|---|---|---|---|
| (2, 2) | 8 | 4 | 4 | 2 / 2 / 4 |
| (3, 5) | 12 | 8 | 4 | 3 / 5 / 4 |
| (5, 5) | 14 | 10 | 4 | 5 / 5 / 4 |
這裡有三件事很明確。
上限每次都剛好是 CONCURRENT + QUEUED。成功回應分別是 4、8、10——也就是每次設定的總和。拒絕數等於超出的部分,而三次測試裡都剛好是 4。
上限是會變動的。它不是映像檔裡寫死的常數,而是你設定多少就是多少。把環境變數從 4 改成 8 再改成 10,這才是它實用的地方,而不是純知識 trivia。
而且這兩個訊號彼此獨立。我的客戶端狀態碼來自真實 HTTP 回應;/pressure 則來自容器內部自己的統計,由另一個執行緒輪詢取得。在這三次短測試中,它們完全一致。這表示 /pressure 可以考慮作為生產環境的監控訊號之一,但還不能直接等同於完整的 autoscaling 合約:輪詢頻率、重置語意、多副本彙總,以及長時間混合工作負載下的行為,都還需要再驗證。
有一個細節,光看 pass/fail 數字會忽略。排隊中的請求不會失敗——它只是等待,而且可能等很久。 在 (2, 2)、工作時間 5 秒的情境下,成功回應的時間落在 5.7 秒到 11.0 秒之間,中位數 8.3 秒。換句話說,端到端延遲大約會到兩個 session 的持續時間。測試環境沒有分開記錄接入與執行時間,所以無法把全部延遲都算成排隊等待。
放到真實任務會長什麼樣子
假設你每天晚上要把 4,000 個商品頁渲染成 PDF,而每個頁面大約要 5 秒。你設定 CONCURRENT=5, QUEUED=5。你的吞吐上限就是每 5 秒 5 個頁面,也就是每秒 1 個頁面;如果整條管線一直維持剛好滿載,整個工作大約要 67 分鐘。這是根據實測行為算出來的數學,不是 benchmark,但在正式部署前,你就應該做這種算術。
任何在所有執行中與排隊名額都被占滿之後才進來的請求,都可能立刻拿到 429;同時送出請求也不保證哪一個編號的請求會輸掉競賽。工作排程器應該把這種回應視為 backpressure,並採用有上限、帶 jitter 的重試。否則它可能會在上層還以為工作正常推進時,悄悄丟掉頁面——這是營運風險,不是這套測試環境有示範出的故障情境。
實作驗證:端點實際看到什麼
為了誠實測試渲染準確性,fixture 頁面會把標記文字藏起來,不讓不是用真正瀏覽器的人看到。可見字串 Runtime Injected Marker 88 是在載入時由 JavaScript 片段組合出來的,因此伺服器送出的任何位元組裡,都不會存在那個連續的字串。對這個頁面的純靜態抓取只會回傳 702 bytes,而且裡面完全沒有那個標記。
| 端點 | 結果 | Bytes |
|---|---|---|
/content | runtime 注入的標記 存在,而且還有兩個靜態標記 | 811 |
/scrape 針對 #scrape-me(JS 注入節點) | 回傳 SCRAPE_TARGET_VALUE_CC | 422 |
/screenshot | 回應包含 PNG 簽章 89 50 4E 47 | 18,621 |
/pdf | 回應包含 PDF 簽章 %PDF- | 40,974 |
| 以上四個,沒帶 token | HTTP 401(不是 403) | — |
/content 回傳 811 bytes 且包含注入標記,代表真的有 Chromium 先把頁面渲染過,HTML 才回來。/scrape 則是從一個只有 JavaScript 跑完才會出現的節點抓出值。這兩者都能運作,且完全不需要 client-side automation code——只要一個已驗證的 POST。
這才是實際賣點。同一輪測試裡,靜態爬蟲完全看不到這類內容,而進程內瀏覽器函式庫(chromedp、rod、Selenium)要等我寫出明確等待條件後才抓得到。Browserless 則只要一個像 curl 的請求就能抓到。你是在用部署重量,換掉 automation 程式碼。
不過這個說法有兩個界線。證據只涵蓋我的 fixture 內容類型,不能代表整個現代網路。還有 /unblock 這個反偵測端點,我是刻意不碰的——以上結果都不應被解讀成 anti-bot 能力宣稱。/function、/download 和 /performance 也都沒有測。
實作驗證:短期殘留檢查
容器化 Chrome 一向有留下殭屍行程的惡名,所以我用 CONCURRENT=3 連續跑了 30 個 session,並在容器內統計行程數。
在信任結果之前,我先校正偵測器。當某個 session 還在進行時,/proc 枚舉器讀到了 11 個 Chrome 家族行程(browser、zygote、GPU、renderers、utilities)。這很重要:它證明這個儀器真的看得到 Chrome,所以結束後的 0 才代表測量結果,而不是視而不見。一個沒先證明自己能數到行程的 leak test,沒有任何價值。
30 個 session 結束後:0 個 chrome 行程、0 個 zombie。 唯一還在的只有 dumb-init、node、Xvfb、start.sh 和 sh。閒置時 /sessions 讀值為 0。
docker stats 看到的容器記憶體(是操作層看得到的數字,不是某個單一行程的 RSS)如下:
| 跑完 N 個 session 後 | 0 | 5 | 10 | 15 | 20 | 25 | 30 |
|---|---|---|---|---|---|---|---|
| 容器記憶體 (MiB) | 294 | 300 | 301 | 302 | 302 | 303 | 303 |
30 個 session 的淨成長大約是 9.5 MB,而且採樣曲線在第 10 個 session 後就趨於平臺。這和短時間內單純線性 per-session leak 的表現不一致。Node warmup 是一個合理的解釋,但這些行程數與記憶體曲線本身無法證明它。
範圍說明:30 個順序 session 只是一次小型 soak,不是 endurance,也不是併發測試。issue tracker 裡長期存在的 EventEmitter listener 警告,可能要過好幾個小時、幾千個 session 才會浮現,而我這次沒有跑到那個程度。能支持的結論只有一個:在這個窗口內、v2.55.0 上,沒有觀察到累積的 Chrome 行程或 zombie。
timeout 邊界
TIMEOUT 文件上說它是個可調旋鈕。我想看看它真的被觸發時會怎樣。
| 情境 | 頁面保持時間 | 狀態碼 | 耗時 |
|---|---|---|---|
| 未超時 | 2,000 ms | 200 | 2.406 秒 |
| 超時 | 15,000 ms | 408 | 5.007 秒 |
當 TIMEOUT=5000 時,嘗試把頁面維持 15 秒的 session 會在 5.007 秒收到 HTTP 408,而不是卡死。這個單一觀察可確認它在接近設定邊界時確實會執行限制。但它沒有揭露計時器實作,也沒有證明 slot 已經清理完成;更強的測試會是重複試驗、觀察 /sessions 和 /pressure 回到閒置狀態,再確認下一個請求能拿到剛釋放的 slot。
遷移陷阱:PREBOOT 沒作用,而且它不會告訴你
在我量到的所有結果裡,這是我最希望在升級前別人先提醒我的一項。
Browserless 2.0.0 移除了 PREBOOT 和 KEEP_ALIVE——changelog 說它們因為容易混淆、實際作用不大,而且還會引發 bug,所以被拿掉了。這個決定本身很合理。真正的問題出在:當 v1 設定被原封不動複製到 v2 時,這正是大家最常用的升級方式。
我用 -e PREBOOT=true 啟動容器,並拿它跟預設值比較:
| 訊號 | PREBOOT=true | 預設、未設定旗標 |
|---|---|---|
| Ready time | 0.716 秒 | 0.776 秒 |
| Cold render | 0.314 秒 | 0.318 秒 |
| Warm render | 0.163 秒 | 0.150 秒 |
| 閒置時的 Chrome 行程數 | 0 | 0 |
所有時間都落在預設組自己的 min–max 範圍內——這只是雜訊,不是效果。而且根本沒有任何預熱:PREBOOT=true 的容器在閒置時一樣沒有保留任何瀏覽器,和沒設這個旗標的容器完全相同。還有兩個訊號,而且都不是數字:
/config完全沒有暴露preboot這個 key。它列出的 key 是concurrent、queued、timeout、token、maxCPU、maxMemory、retries等等。- 沒有 error。沒有 warning。容器 log 也什麼都沒有。
所以,v1 的 PREBOOT 設定搬到 v2 後,在正常啟動與 log 檢查下就是靜默失效。可偵測的訊號是:/config 少了那個 key,而且行為也沒有改變;Browserless 不會明講拒絕或發出警告。遷移時不能只看啟動成功,就以為每個環境變數都生效了。
KEEP_ALIVE 則是相反的情況,這兩者不能混為一談。 它也是在同一版被移除,但它不是靜默的——我用 spot probe 看容器時,它會在 stdout 裡明確印出 Environment variable of "KEEP_ALIVE" is deprecated and ignored. 這樣的訊息。這才是對操作人員友善的警告。我沒有把 KEEP_ALIVE 放進和 PREBOOT 一樣的量測流程裡,所以這裡把它當作檢查結果來報告,而不是量測值。不過方向已經夠清楚了:只有 PREBOOT 是那個靜默陷阱。 若只用一句「v2 會忽略你的 v1 旗標」來概括,反而低估了 Browserless 對 KEEP_ALIVE 的誠實程度。
優缺點
優點
- 接入控制的行為和文件描述完全一致,而且會隨設定變動——在三個不同上限下都已驗證,客戶端狀態碼與伺服器自己的統計同時吻合。
/pressure在三次短測試中都和客戶端看到的 running、queued、rejected 數量一致;可以把它當成 autoscaling 與告警的候選輸入之一。- 真的用了 Chromium 來渲染,而且不需要任何 client-side automation code:一個已驗證的 POST 就能把 JS 注入的 DOM 內容抓出來,這是靜態抓取看不到的。
- 在 30 個 session 的順序執行中,沒有看到 Chrome 行程累積;跑完後仍是 0 個 Chrome 行程、0 個 zombie。
- 有一次
TIMEOUT測試在 5.007 秒回 408,設定值是 5.000 秒;但沒有另外驗證清理與 slot 釋放。 - 預設就有驗證:沒有 token 時,四個 REST 端點都會回 401。
- 從
docker run到可用服務約 0.78 秒,之後第一次渲染約再 0.32 秒。
缺點
- 4.34 GB 映像檔。 這是最誠實的成本標題,而且會反映在你的 registry、CI cache 和冷部署時間上。
- SSPL-1.0 或 Browserless 商業授權。 請把最新條款和你的部署與散佈模式逐一對照。
- v1 的
PREBOOT在 v2 仍可接受,但會被靜默忽略——沒有 error、沒有 warning、也沒有/configkey。 - 你是在操作一個服務,而不是單純新增一個 dependency:容器、token、網路路徑、接入上限,以及升級責任,都是你的。
- 在
(2, 2)測試中,排隊請求把端到端延遲推到大約兩個 session 的時間;沒有單獨量到排隊等待。 - 這次量到的 REST 時間包含一次 HTTP 往返,無法把 browser 啟動成本單獨拆出來,也無法證明瀏覽器重用。
誰適合用,誰不適合
當不只一件事需要瀏覽器時,Browserless 就很有價值。例如:一個給多個應用共用的渲染服務、想透過 HTTP 端點拿到截圖與 PDF,而不是讓每個服務都依賴 Chrome 的團隊、或是確實需要可量化容量上限與 backpressure 的工作管線——這些都很適合。如果你已經在跑 Docker,而且有人負責部署,那營運故事就很清楚:可預期的接入、可觀測的 backpressure,以及在 30 個 session 順序檢查中沒有觀察到累積的 Chrome 行程或 zombie。
如果你本來的替代方案是讓 stack 裡每個服務都各自安裝 Chromium,那把它集中到一個有 token 和容量上限的容器裡,這確實是一筆合理的架構交易。
如果你只是要寫一支小腳本,就別用它。為了讓單一 Python 檔去抓一個已渲染頁面,就得拉 4.3 GB 並跑一個容器,對小工作來說太繁瑣了——進程內的 browser library 根本不需要額外的服務部署就能做到。若 SSPL 條款與你的商業產品不合,而且也談不攏,那就別用它。如果你真正想要的是一個天生預熱、沒有冷啟動成本的瀏覽器,那 PREBOOT 在 v2 不會幫你做到。若你的真問題其實是反爬處理,那也不適合,因為那屬於我刻意沒測的端點,也不會替它背書。
替代方案,以及 Thunderbit 在哪裡
真正值得比較的,不是 Browserless 跟另一個容器,而是瀏覽器放在哪裡,以及誰負責把它維持在線上。
相關評測:Browsertrix Crawler review。
相關評測:chromedp review。
| 瀏覽器函式庫(chromedp、rod、Selenium、Playwright) | 自架 Browserless | Thunderbit 代管擷取 | |
|---|---|---|---|
| 瀏覽器在哪裡跑 | 在你的進程裡 | 在你的容器裡 | 別人的基礎設施上 |
| 設定成本 | 安裝套件 | 4.3 GB 映像檔 + 容器 + token | API key |
| 這裡量到的時間 | 本文未量測 | HTTP ready 後第一次渲染 0.32 秒;後續請求中位數 0.15 秒 | 本文未量測 |
| 你要寫什麼 | 帶明確等待條件的 automation code | 一個已驗證的 POST | 一個 HTTP 呼叫 |
| 回傳什麼 | 你寫了什麼就回什麼 | HTML、符合簽章的 PNG/PDF 回應、被抓取的節點 | 產品專屬的結構化 JSON 或 Markdown |
| 容量上限 | 你的機器 | CONCURRENT + QUEUED,之後回 429 | 依供應商方案而定 |
| 誰值班 | 你 | 你 | 他們 |
如果你想把瀏覽器放在自己的進程裡,而且不介意自己寫等待條件,那函式庫會更輕,還不需要部署服務。我在 Playwright versus Puppeteer comparison 和更廣泛的 open-source scraping project roundup 也整理過那一側的比較。
如果你根本不想自己維運瀏覽器,那我們自己的 Thunderbit 就是其中一個代管替代方案。Browserless 會把渲染後的內容交給你,由你的程式去解讀;Thunderbit 則可以在供應商負責渲染基礎設施的前提下,回傳 Markdown 或 schema 對應後的資料。本文沒有對 Thunderbit 的延遲、容量、失敗行為、擷取品質或成本做 benchmark,所以這張表講的是責任邊界,而不是效能比較。
同一輪測試裡的相關閱讀:Crawl4AI review 介紹的是你自己維運的瀏覽器驅動 Markdown 管線,而 web scraping tools overview 則整理了整個更大的類別。
結論
要不要跑 Browserless?如果有多個呼叫端需要瀏覽器工作、有人能操作這個容器,而且你的授權審查也同意這種部署模式,那答案是可以。在三組合成式接入測試中,成功數都等於 CONCURRENT + QUEUED,超出的部分回 429,而 /pressure 也和客戶端可見數量一致。另一次 30 個 session 的順序檢查中,沒有累積 Chrome 行程或 zombie。一次 timeout 試驗也在設定邊界附近回 408。這些都是有意義、且範圍受限的觀察,不是放諸四海皆準的保證。
不過,還是要誠實面對成本。它是一個 4.34 GB 的映像檔,也是一個你要自己操作的服務,不是你隨手加進去的依賴;這次測試沒有建立它和進程內瀏覽器函式庫之間的速度比較。它真正給你的,是一個可以配額化的瀏覽器:有明確上限,也有可觀測的 backpressure。在 30 個 session 順序檢查裡,沒有觀察到任何累積的 Chrome 行程或 zombie。代價則是部署重量,以及你必須認真閱讀的授權。如果你只是要從單一腳本渲染幾個頁面,這筆交易不划算;如果你要的是一層被多個服務依賴的渲染能力,那就划算——只是在上線前,記得把 v1 的環境變數檢查一遍,因為 PREBOOT 只會裝作有在工作,實際上什麼都沒做。
試試 Thunderbit 進行網頁資料擷取 Get Started Free
常見問題
Browserless 會讓 headless Chrome 變快嗎?
這次測試無法回答。HTTP 端點在 docker run 之後 0.78 秒就能回應;接著第一次 /content 呼叫花了 0.32 秒,同一容器後續呼叫大約是 0.15 秒。這些數字混在一起包含了 HTTP 往返、瀏覽器工作、導向與回應傳輸。測試環境沒有把啟動時間獨立拆開,也沒有追蹤行程重用,更沒有發布可對照的進程內 benchmark。你應該把 Browserless 當作共享服務邊界與接入控制來用,然後自己 benchmark 你的實際延遲路徑。
超過 Browserless 的併發限制會怎樣?
會立刻收到 HTTP 429。上限就是 CONCURRENT + QUEUED,我在三組設定下都確認過:(2,2) 接受 4 個、拒絕 4 個;(3,5) 接受 8 個、拒絕 4 個;(5,5) 接受 10 個、拒絕 4 個。伺服器的 /pressure 每次都回報一致的 running、queued 與 recentlyRejected 數量。值得注意的是:排隊中的請求不會失敗,它只是等待——在 (2,2) 且每個任務 5 秒的情境下,成功回應耗時介於 5.7 秒到 11.0 秒。你的 client 應該把 429 當成 backpressure,並使用 retry 與退避策略。
Browserless v2 還支援 PREBOOT 嗎?
不支援。PREBOOT 在 2.0.0 已被移除,而 v2 會接受 -e PREBOOT=true,卻不會報錯也不會警告,實際上什麼都不做。我從三個角度確認它是惰性的:延遲和預設值沒有差別、閒置的 PREBOOT=true 容器沒有任何等待中的 chrome 行程,而且 /config 裡根本沒有 preboot 這個 key。如果你是從 v1 設定遷移過來,實例並不會被預熱。要注意,同版本移除的 KEEP_ALIVE 會記錄一條「deprecated and ignored」警告——所以這個靜默失效的問題只出現在 PREBOOT。
Browserless 可以免費用在商業用途嗎? 這個儲存庫提供 SSPL-1.0 或 Browserless 商業授權,但本文不會把特定商業或閉源情境對應到某一種授權。請先閱讀最新的 LICENSE 與 官方部署指引,再由負責軟體授權的人評估你的部署與散佈模式。
Browserless 會留下 zombie Chrome 行程嗎?
在這次短時間測試裡沒有累積。30 個順序 session 之後,容器裡是 0 個 Chrome 行程、0 個 zombie,只剩 dumb-init、node、Xvfb、start.sh 和 sh。偵測器在 session 進行時曾數到 11 個 chrome 家族行程,所以它不是看不見。容器記憶體從 294 MiB 增加到 303 MiB 後就趨於平臺。這不是長時間、併發或上千 session 的耐久結果。


