跳到主要內容
← 回找工具
現場紀錄

同一個字型網址,用程式抓到的是另一份

想把中文網頁字型改成自架,我用程式把樣式表抓下來。它回 200、內容也是合法的 CSS,但只有兩個字型檔、每個 7 MB。瀏覽器拿到的是同一個網址的另一個版本:兩百多個切片、每片幾十 KB。它不是壞了,是看你是誰。

2026-09-19 · 作者整理:Lucas

我要把網站的中文字型從線上載入改成自己放,理由是隱私:不想每個訪客都連一次別人的伺服器。第一步很自然,把那行樣式表網址用程式抓下來看看裡面指到哪些檔。

它回 200。內容是乾淨的 CSS,兩個 @font-face,一個常規、一個粗體,指向兩個 .ttf 檔。

我把兩個檔下載下來,才發現每一個都 7 MB。

同一個網址,三種身分,三種答案
────────────────────────────────────────────
  誰在問            回什麼          大小
────────────────────────────────────────────
  curl              2 個 @font-face   466 B
                    truetype        單檔 7,090,820 B
  Firefox 38        2 個 @font-face   460 B
                    woff            單檔 4,161,364 B
  Chrome 131      210 個 @font-face   240,368 B
                    woff2 切片      每片約 9 KB 起
────────────────────────────────────────────
  三次都是 HTTP 200

我以為發生了什麼

我以為樣式表就是一個檔案:網址固定,內容固定,誰來抓都一樣。所以我把程式抓到的那份當成瀏覽器平常用的那份,開始盤算「兩個 7 MB 的字型檔要怎麼快取」。

我甚至覺得中文字型本來就這麼大,這是自架的代價。

實際發生了什麼

2026-09-19 實測,同一個 css2 網址,只換 User-Agent。

用 curl 的預設身分抓:466 位元組,2 個 @font-face,格式 truetype,字型檔 HEAD 回 7,090,820 位元組。換成 2015 年的 Firefox 38:460 位元組,2 個 @font-face,格式 woff,單檔 4,161,364 位元組。換成 Chrome 131:240,368 位元組,210 個 @font-face,格式 woff2,而且每一個都帶 unicode-range,把中文字集切成 105 片一組、兩個字重共 210 片,瀏覽器只下載頁面上真的用到的那幾片。

同一個網址,回應的樣式表差了五百倍,字型檔的切法完全不同。 三次都是 200,三次都是合法 CSS,沒有任何一次提示「你拿到的是降級版」。

回應標頭裡其實有線索:Cache-Control: private,還有一個 Vary 標頭。private 的意思就是這份內容是針對你這個請求端產的,不能拿給別人用。我第一次抓的時候沒看它。

官方文件寫了嗎

有寫,但寫在「為什麼要用我們的線上服務」那一段,不是寫在「自架時要注意」那一段。官方說明服務會依瀏覽器送出最適合的格式,這句話本身就是答案:它依瀏覽器決定內容,而 curl 不是瀏覽器。

工具沒做錯。給一個不認得的客戶端最保守的格式,是合理的設計。錯的是我把「依瀏覽器產生的樣式表」當成靜態檔在抓。 它沒有騙我,它只是照我的身分回答。

你一定會踩的那個細節

真正會踩到的不是字型變大,是你拿程式抓下來的那份去自架,然後在正式環境量到「每個訪客第一次載頁要多下載 7 MB」,卻以為那是中文字型的天性。

抓樣式表的時候,把 User-Agent 換成你的使用者真的在用的瀏覽器,並且抓完先數 @font-face 有幾個。 今天就能自己跑一次:

同一個網址抓三次,只換身分:

U="https://fonts.googleapis.com/css2"
U="$U?family=Noto+Sans+TC:wght@400;700&display=swap"

1. 程式預設身分
   curl -s "$U" | grep -c "@font-face"
   → 看到 2,就是保守版

2. 換成現代瀏覽器
   UA="Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
   UA="$UA AppleWebKit/537.36 (KHTML, like Gecko)"
   UA="$UA Chrome/131.0.0.0 Safari/537.36"
   curl -s -A "$UA" "$U" | grep -c "@font-face"
   → 看到 210,這才是瀏覽器拿到的那份

3. 看它是不是「看人給」
   curl -sI "$U" | grep -i "cache-control\|vary"
   → private 加 Vary,就代表內容隨請求端變

數字差一百倍,就不要把第 1 步那份拿去自架。

第 3 步平常就該養成習慣:任何回 Cache-Control: private 的東西,都不要當成「抓一次、大家共用」的靜態檔。

站內延伸

來源: fonts.googleapis.com/css2 端點(Noto Sans TC 400/700)與 fonts.gstatic.com 字型檔的 HEAD 回應,三種 User-Agent 各一次,皆為 2026-09-19 當日實測。

一個網址不一定對應一份內容。回 200 只證明它願意回答你,不證明它回答的是你要問的那一版;當回應標頭寫著 private,它其實已經告訴你了。

← 看更多找觀念文章
取得 AI 實戰工具與更新

之後會不定期整理:新方法、指令包(Prompt Pack)、Checklist 與模板。免費、無廣告;送出後會收到一封確認信,點了連結才算訂閱成功,之後每封信都附一鍵退訂。