返回部落格
技術科普

圖片貼到別站就變破圖?403 與防盜連完整排錯樹(2026 更新)

發佈於17 min read
分享文章

你把一張圖的連結貼到部落格,本機預覽好好的。發布出去,別人看到的卻是一個破掉的圖示框。或者更糟——整張圖位置變成一片空白,什麼都沒有。

這個坑我踩過不只一次。線上炸過一次是幫朋友的論壇搬圖,本地全綠,上線後首頁三分之一的縮圖全破,當時我還以為是快取沒清。debug 了三天才發現,根本不是我的問題——是圖片來源站開了防盜連(hotlink protection),只要不是從它自己的網域發出的請求,一律擋掉。

從架構角度來看,「圖片在別站顯示不出來」其實是三種完全不同的失敗被混在一起講。要修對,第一步是先分清楚你遇到的是哪一種。

先分清楚:403、破圖、200 空白是三件事

很多人一看到圖不見就統稱「破圖」,然後亂試一通。說穿了,這三種症狀的根因差很遠,對應的排錯路徑也不一樣。

症狀 HTTP 狀態碼 最可能的根因 排錯方向
破圖示框(圖示裂開) 403 / 404 防盜連擋掉、或連結本身就錯 查 Referer 與網址正確性
破圖示框(圖示裂開) 200 但非圖片 拿到的是 HTML 錯誤頁不是圖檔 查 Content-Type
一片空白(無裂圖示) 200 CSS 蓋住、或 CSP 擋載入 查 DevTools Console 與 CSP
圖示轉圈後消失 逾時 / CORS 跨網域政策或伺服器超時 查 Network 的 request 細節

先看狀態碼,再看 Content-Type,最後才看畫面。這順序反過來就會鬼打牆。

底層原理:Referer 與防盜連怎麼運作

要理解為什麼別站的圖會被擋,得先知道瀏覽器在載圖時偷偷做了什麼。

當網頁 A 用 <img src="https://B.com/photo.jpg"> 去載 B 站的圖,瀏覽器發出的請求會夾帶一個 Referer 標頭(對,這個字歷史上就拼錯了,少一個 r,將錯就錯到今天)。這個標頭告訴 B 站:「這張圖是被 A 站的頁面請求的。」

底層原理是這樣:B 站的伺服器或 CDN 收到請求後,會拿 Referer 的網域去比對一份白名單。比對邏輯大致是——

1. Referer 是空的(直接開圖、書籤)→ 看設定決定放行或擋
2. Referer 的網域在白名單 → 放行
3. Referer 的網域不在白名單 → 回 403 Forbidden

這就是防盜連。它的目的很單純:不想讓別人白嫖自己的頻寬。你在自己站上嵌了 B 站的圖,每一次別人瀏覽你的頁面,流量帳都算在 B 站頭上,B 站當然不爽。

這邊有個細節很多人不知道:現代瀏覽器預設的 Referrer-Policy 是 strict-origin-when-cross-origin。跨網域請求時,它只送出「來源網域」(例如 https://a.com/),不會送完整路徑。所以防盜連拿得到你的網域名稱,足夠拿來比對白名單、也足夠擋你。這就是為什麼防盜連對付得了 hotlink。

為什麼你的圖在別站變破圖:一棵排錯樹

把上面的原理攤開,破圖的根因其實可以收斂成一棵樹。你照著往下走就好。

分支一:狀態碼是 403 嗎?

是的話,九成是防盜連。B 站看到你的 Referer 不在它的白名單,直接拒絕。這種情況你改不了 B 站的設定,唯一的解是別再 hotlink 它的圖(後面講正解)。

分支二:狀態碼是 200,但畫面破圖?

打開這張「圖」的原始內容看看。很可能你拿到的是一頁 HTML——某些站不回 403,而是回一個「請勿盜連」的提示頁,狀態碼還是 200。瀏覽器把 HTML 當圖片解析,當然裂給你看。查 Content-Type 就露餡了:正常圖片是 image/jpeg、image/png,錯誤頁會是 text/html。

分支三:你貼的是「頁面連結」不是「圖片直連」?

這是新手最常見的雷。https://imgur.com/aBcDeFg 是一個頁面,https://i.imgur.com/aBcDeFg.jpg 才是圖片檔案本身。前者你用 <img src> 去載,拿到的是一整頁 HTML,不是圖。差一個 i. 和副檔名,結果天差地遠。

分支四:Referrer-Policy 把你自己害了?

比較隱蔽的一種。如果你的頁面設了 Referrer-Policy: no-referrer,瀏覽器載圖時完全不送 Referer。有些防盜連設定是「空 Referer 一律擋」,於是你反而被自家的隱私設定擋在門外。實測下來,這種案例通常出現在很在意隱私、把 meta referrer 關死的站。

動手診斷:DevTools 與 curl 兩招定位

理論講完,實際怎麼查?我固定用兩個工具,五分鐘內能定位九成的破圖。

第一招:DevTools Network 面板

打開瀏覽器開發者工具(F12),切到 Network,重新整理頁面,在過濾器打圖片檔名。點進那筆請求,看三個東西:

  • Status:是 403、404 還是 200?
  • Response Headers 的 Content-Type:是 image/* 還是 text/html?
  • Request Headers 的 Referer:實際送出去的是什麼?空的還是你的網域?

三個看完,根因大概就浮出來了。

第二招:curl 手動控制 Referer

DevTools 看得到現象,但要驗證「到底是不是防盜連」,curl 最乾脆。你可以手動塞任意 Referer,看伺服器反應怎麼變:

# 完全不帶 Referer(模擬直接開圖)
curl -I "https://example.com/photo.jpg"

# 帶一個「假裝來自來源站自己」的 Referer
curl -I -H "Referer: https://example.com/" "https://example.com/photo.jpg"

# 帶一個「來自你的外部站」的 Referer
curl -I -H "Referer: https://your-blog.com/" "https://example.com/photo.jpg"

判讀方式很直觀。如果第一、三個回 403,但第二個回 200——恭喜,實錘防盜連。伺服器只認來源站自己的 Referer,其他一律擋。如果三個都 200,那破圖就跟防盜連無關,回頭查你的網址或 CSP。

我實測的習慣是三條一起跑,對照結果比單看一條清楚太多。這就是為什麼 curl 比在瀏覽器裡瞎點有效率。

常見圖床 / CDN 的防盜連行為

不同服務的預設脾氣差很多。下面是我這幾年搬圖踩下來的觀察,實際設定各家可能隨時調整,但大方向如此。

服務類型 預設是否防盜連 空 Referer 行為 適合外站直連?
自架 Nginx / Apache 看你怎麼設 通常放行 看設定
企業級 CDN(可設白名單) 可開可關 可設放行或擋 設對就可以
部分免費圖床 常開 常擋 常被擋
社群平台的圖片網域 幾乎都開 幾乎都擋 不行,別想
主打分享的圖床 通常關 放行 可以,這才是它存在的意義

重點是最後一列。社群平台(那些社交網站的 CDN 網域)的圖,你複製出來的網址幾乎百分之百不能外連,因為它們的商業模式就是把你鎖在站內。想拿那些圖去別處貼,死路一條。

而主打「分享」的圖床,防盜連預設是關的——它的存在意義就是讓你的圖能穩定被外站載到。這兩類千萬別搞混。

Referrer-Policy 的陷阱:連瀏覽器都可能反過來害你

前面提過一種隱蔽狀況,這裡展開講,因為它最容易讓人 debug 到懷疑人生。

Referrer-Policy 是頁面(發出請求那一方)可以設定的標頭。它決定瀏覽器要送出多少 Referer 資訊。值有好幾種:

  • no-referrer:完全不送。
  • origin:只送來源網域。
  • strict-origin-when-cross-origin:跨網域只送網域、降級到 HTTP 就不送(現代預設值)。
  • unsafe-url:連完整路徑都送(不建議,會漏隱私)。

矛盾點在這裡。防盜連要靠 Referer 判斷來源,但隱私政策卻鼓勵少送甚至不送 Referer。當一個站基於隱私設了 no-referrer,它去載任何有防盜連、又「空 Referer 一律擋」的圖,就會全部破掉。

我線上炸過一次就是這種——某個很重視隱私的站,全站掛了 no-referrer,結果所有外連圖全破。當時我還以為是圖床掛了,查了半天才發現是自己的 meta 設定把 Referer 掐死。這個雷不容易想到,因為「加強隱私」聽起來怎麼會害到自己?

正確做法:別 hotlink 別人的圖

排錯到最後,你會發現一個殘酷事實:只要圖不是你自己托管的,任何「別站的圖」都可能在你無法控制的時刻消失。對方改防盜連、換網址、砍檔案、甚至整站關掉,你的頁面就跟著破。

真正穩的做法只有兩條。

第一,把圖重新托管到自己能控制的地方。 別直接嵌別人的網址。把圖下載下來、上傳到你自己的空間或一個允許外連的圖床,改用那個穩定網址。從架構角度看,這一步的本質是把你頁面的可用性,從別人的伺服器手上拿回到自己手上——只要來源不是你能掌控的,對方任何一次防盜連調整、網址結構改版、甚至整站下線,都會直接反映成你頁面上的破圖,而且你連預警都收不到,往往是讀者回報才知道炸了。如果你手上已經有一整批散落在別人網域的舊連結要一次搬乾淨,我另外寫過一篇 圖片連結批次替換的完整 SOP,用腳本掃出全站舊網址一次替換,比手動一張張換省事太多。能控制的來源,才是穩的來源。

第二,選一個防盜連預設是關的圖床。 很多免費圖床為了省頻寬會擋外連,貼到論壇或部落格就破給你看。要外連,就挑一個明確允許直連的服務。

這也是我們做 lpic.cc 時的一條原則:上傳後給你的是穩定的圖片直連網址,不預設擋外站,讓你貼到論壇、部落格、Discord 都能正常顯示,不會莫名其妙變 403。需要私密的圖,也能用密碼保護控制誰看得到。想試的話,免費上傳 一張圖,把連結貼到別的頁面測一下就知道穩不穩。

老實說也得誠實講限制:目前免費方案的圖有 30 天保存期,不是永久存檔,而且服務靠廣告營收支撐。長期典藏或商用大量圖庫,你該評估付費的專業方案,或自己架設有備份的儲存。工具挑對場景才有意義——這點我踩過雷才學乖。

常見問題 FAQ

Q:為什麼同一個圖片連結,我自己開得起來,貼到別站就破?

因為你「直接開圖」時 Referer 是空的、或來自允許的來源,防盜連放行。貼到別站後,Referer 變成那個外部網域,不在白名單,就被擋成 403。同一個網址、不同的 Referer,結果完全不同。

Q:403 和破圖是同一件事嗎?

不是。403 是伺服器明確拒絕(狀態碼 403),破圖只是瀏覽器「畫不出圖」的畫面表現。403 會造成破圖,但破圖也可能來自網址錯、Content-Type 錯、CSP 擋載入等其他原因。先看狀態碼才知道是哪種。

Q:把頁面設成 Referrer-Policy: no-referrer 能繞過防盜連嗎?

有時候可以,有時候反而更慘。如果對方的防盜連是「空 Referer 放行」,不送 Referer 確實能過。但如果對方是「空 Referer 一律擋」,你反而全破。這招不可靠,別當正解用。

Q:我用程式(Python / Node)抓圖也被 403,怎麼辦?

跟瀏覽器同理——你的程式沒帶對 Referer。用 curl 先測出對方認哪個 Referer,再在你的 HTTP 請求裡補上同樣的標頭。但請注意:繞過別人的防盜連去抓圖,可能違反對方服務條款,自己拿捏。

Q:怎麼快速判斷一個圖床能不能外連?

上傳一張測試圖,拿它的直連網址,用 curl -I -H "Referer: https://google.com/" 跑一下。回 200 就是允許外連,回 403 就是有防盜連、別拿來貼外站。三十秒驗完。

References

#防盜連#hotlink protection#403 Forbidden#Referer#Referrer-Policy#CDN#圖片直連
H

作者

Harvey Zhang

共同創辦人兼 CTO

後端工程師出身,從系統架構角度深度解析圖片託管服務的技術實現。