最近我遇到一個 GitHub 圖片載入的問題
我習慣把 Blog 使用的一些圖片放在 GitHub Repository,網站直接使用 GitHub Raw URL 顯示圖片
原本一直都正常,但最近在單一 Client 一次讀取比較多圖片時,突然開始出現下面的錯誤
429: Too Many Requests For more on scraping GitHub and how it may affect your rights, please review our Terms of Service
(https://docs.github.com/en/site-policy/github-terms/github-terms-of-service).

最後我的處理方式很簡單,也是 AI 提示我的 就是改走 jsDelivr CDN 不要讓 Client 直接讀取 GitHub Raw
另外 GitHub 在點擊 Raw 或取得圖片網址時,也可能拿到這種格式:
https://github.com/donma/BlogResource/blob/main/2569/264203.png?raw=true
這兩種網址直接丟到瀏覽器都可以正常顯示圖片
所以一開始我也沒有特別處理
但問題就在於,GitHub Raw 可以讀取圖片,不代表適合直接拿來當網站的圖片 CDN
當同一個 Client 在短時間內載入大量圖片時,就有機會直接收到:
429: Too Many Requests,可能最近因為 vibe coding 問一下 AI 好像再 2025 下半年開始陸續出現這問題..
1. 簡單的說就是改寫網址把網址改成
網址格式如下:
https://cdn.jsdelivr.net/gh/{owner}/{repo}@{branch}/{path}
例如原本:
https://raw.githubusercontent.com/donma/BlogResource/refs/heads/main/2569/0331-03-42.jfif
轉換後:
https://cdn.jsdelivr.net/gh/donma/BlogResource@main/2569/0331-03-42.jfif
另一種 GitHub Blob URL:
https://github.com/donma/BlogResource/blob/main/2569/264203.png?raw=true
轉換後:
https://cdn.jsdelivr.net/gh/donma/BlogResource@main/2569/264203.png
其實規則不複雜。
GitHub Raw:
/{owner}/{repo}/refs/heads/{branch}/{path}
GitHub Blob:
/{owner}/{repo}/blob/{branch}/{path}
最後統一轉成:
/{owner}/{repo}@{branch}/{path}
2. 這邊提供一個 C# function ,之後你就可以無腦使用
using System;
using System.Linq;
public static string ToJsDelivrUrl(string url)
{
if (string.IsNullOrWhiteSpace(url))
{
return url;
}
Uri uri;
if (!Uri.TryCreate(url, UriKind.Absolute, out uri))
{
return url;
}
string[] segments = uri.AbsolutePath
.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
string owner;
string repository;
string branch;
string filePath;
if (uri.Host.Equals(
"raw.githubusercontent.com",
StringComparison.OrdinalIgnoreCase))
{
if (segments.Length < 4)
{
return url;
}
owner = segments[0];
repository = segments[1];
if (segments.Length >= 6 &&
segments[2].Equals(
"refs",
StringComparison.OrdinalIgnoreCase) &&
segments[3].Equals(
"heads",
StringComparison.OrdinalIgnoreCase))
{
branch = segments[4];
filePath = string.Join("/", segments.Skip(5));
}
else
{
branch = segments[2];
filePath = string.Join("/", segments.Skip(3));
}
}
else if (uri.Host.Equals(
"github.com",
StringComparison.OrdinalIgnoreCase))
{
if (segments.Length < 5 ||
!segments[2].Equals(
"blob",
StringComparison.OrdinalIgnoreCase))
{
return url;
}
owner = segments[0];
repository = segments[1];
branch = segments[3];
filePath = string.Join("/", segments.Skip(4));
}
else
{
return url;
}
if (string.IsNullOrWhiteSpace(filePath))
{
return url;
}
return string.Format(
"https://cdn.jsdelivr.net/gh/{0}/{1}@{2}/{3}",
owner,
repository,
branch,
filePath);
}記得加入:
using System;
using System.Linq;
這個 function 目前支援:
https://raw.githubusercontent.com/{owner}/{repo}/refs/heads/{branch}/{path}
https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{path}
以及:
https://github.com/{owner}/{repo}/blob/{branch}/{path}?raw=true
如果不是 Github 圖片網址,就直接回傳原本的 URL
最後說個結論,其實一值把圖片在 Github 上不一定是好事,但是之前就這樣規畫了
所以這目前是一個快速解決的方法,最好的方式還是自己 own 圖片但是就是得自己扛流量
這次遇到 GitHub Raw 回傳 429: Too Many Requests,才發現原本一直可以正常讀取
不代表這個使用方式就適合網站長期使用,改到 jsdelivr 應該是目前最簡單的解法
紀錄一下,給之後遇到有需要的人 :)
---
The bug existed in all possible states.
Until I ran the code.