Discord CDN Proxy
useapi.net
Posted on May 13, 2024
Host your images and videos on Discord CDN
Suppose you want to take advantage of the free Discord CDN to host your images or videos. With the simple script below, you can upload your assets to a desired Discord channel:
curl -X POST "https://discord.com/api/v10/channels/<Discord channel>/messages" \
-H "Authorization: <Discord token>" \
-F 'payload_json={"content":"Here is your file!","attachments":[{"id":0,"filename":"<file name>"}]}' \
-F 'files[0]=@<path to file name>'
Example:
curl -X POST "https://discord.com/api/v10/channels/123456789/messages" \
-H "Authorization: ABc.your.discord.token.xYZ" \
-F 'payload_json={"content":"Here is your file!","attachments":[{"id":0,"filename":"source.jpg"}]}' \
-F 'files[0]=@./source.jpg'
Please refer to our guide on how to obtain your Discord token and set up a private channel. Omit the Midjourney setup steps if you do not plan to use it.
Response JSON will contain attachments[0].url
with Discord CDN attachment link.
Create a Proxy for Discord CDN
Starting December 2023 all Discord CDN attachment links have following format: https://cdn.discordapp.com/attachments/channel/message/filename.ext?ex=EXPIRES&is=ISSUED&hm=CODE
Query parameters values EXPIRES
and ISSUED
are timestamps in unix/epoch hex format, CODE
is encoded checksum used to verify EXPIRES
and ISSUED
values.
Attempt to retrieve Discord CDN attachments URL without above query parameters or with EXPIRES
past current time will result in 404 This content is no longer available.
response, see example.
In practical terms this means that you can no longer link attachments from Discord on your website, share them on Reddit, Facebook.
This article provides you with effective solution to continue sharing your Discord CDN content publicly without incurring any costs.
The Discord CND proxy especially handy for users of Midjourney API, Pika API or InsightFaceSwap API.
Once your public proxy deployed you can use public image links using https://your-discord-cdn-proxy-url/?https://cdn.discordapp.com/attachments/channel/message/filename.ext
format.
These links can be shared publicly, published on your website, etc.
The proxy will refresh the links provided after the ?
and redirect the browser to the refreshed Discord CDN link.
You can include original Discord attachment link query parameters as well ?ex=EXPIRES&is=ISSUED&hm=CODE
, the proxy will check if the link has expired, and may return the original URL immediately if it is not expired.
When responding with HTTP 302 the proxy will set response headers Expires with link expiration time.
Custom response header x-discord-cdn-proxy
will be set to one of following values:
-
original
- provided link query parameters?ex=EXPIRES&is=ISSUED&hm=CODE
indicate that link is still "fresh" -
refreshed
- call tohttps://discord.com/api/v9/attachments/refresh-urls
Discord API was made to retrieve refreshed link -
memory
- refreshed link returned from the memory cache -
bucket
- refreshed link returned from the R2 bucket cache (optional for Cloudflare Worker deployment)
Original Discord CDN link open (404: This content is no longer available.
)
Discord CDN link using proxy open
Discord CDN link using proxy (without query parameters) open
Two deployment options covered in the article:
- Google App Engine instructions.
- Cloudflare Worker instructions.
- 100K requests per day are included in the free tier account link.
- Cloudflare does not require the entering of payment information.
You can choose either option based on your preferences.
The source code for Google App Engine is a standard Node.js Express server.
You can deploy it in any compatible environment, see the instructions below:
Deploy Google App Engine
Assuming you have Google Cloud account and installed gcloud CLI.
Clone git repository discord-cdn-proxy.
Navigate to ./google-app-engine
folder and install npm packages:
npm install
You can follow along the official Google App Engine deployment steps for Node.js.
Log in to your Google Cloud account:
gcloud auth login
Create new project:
gcloud projects create discord-cdn-proxy
Select created project:
gcloud config set project discord-cdn-proxy
Find created project on your Google Cloud Dashboard and link billing account to the project.
Create App Engine project:
gcloud app create
Create .env.yaml
file with following yaml:
env_variables:
DISCORD_TOKEN: "discord token"
CHANNELS: "['channel id', 'another channel id', 'channel id etc']"
How to extract discord token.
Optional array CHANNELS
defines which Discord channels should be proxied.
You can remove it but it is strongly not recommended for public proxies.
Deploy App Engine project:
gcloud app deploy
You may have to run the above command a few times, as it often fails on the first run.
Notice the name of the deployed service, which will look like:
Deployed service [default] to [https://discord-cdn-proxy.it.r.appspot.com]
Update .env.yaml
file and add DISCORD_CDN_PROXY_URL with value from deployed service:
env_variables:
DISCORD_TOKEN: "discord token"
CHANNELS: "['channel id', 'another channel id', 'channel id etc']"
DISCORD_CDN_PROXY_URL: "https://discord-cdn-proxy.it.r.appspot.com"
Deploy App Engine project with updated configuration:
gcloud app deploy
Now you can test deployed proxy.
Example (adjust to include actual values): https://discord-cdn-proxy.it.r.appspot.com/?https://cdn.discordapp.com/attachments/channel/message/filename.ext
Debugging locally
Update DISCORD_TOKEN value in your package.json
file:
{
"name": "discord-cdn-proxy",
"version": "1.0.0",
"description": "Discord CDN proxy",
"main": "server.js",
"type": "module",
"scripts": {
"start": "node server.js",
"debug": "DISCORD_TOKEN='discord token' DISCORD_CDN_PROXY_URL='http://localhost:8090/' node server.js"
},
"author": "useapi.net",
"license": "ISC",
"dependencies": {
"express": "^4.19.2"
}
}
Execute script with npm:
npm run debug
Deploy Cloudflare Worker
Assuming you have free Cloudflare account setup completed and installed Wrangler CLI.
Clone git repository discord-cdn-proxy.
Navigate to ./cloudflare-web-worker
folder and install npm packages:
npm install
If you are familiar with Cloudflare Workers, you can adjust the deployment configuration in the wrangler.toml
file.
You can fine-tune it later at any time once you have acquired some initial experience.
Deploy Worker:
wrangler deploy --keep-vars
Notice deployment url which will look like https://discord-cdn-proxy.your-user-name.workers.dev
You can use that url to test by adding Discord link at the end after ?
Example: https://your-discord-cdn-proxy-url/?https://cdn.discordapp.com/attachments/channel/message/filename.ext
Create .secrets
file with following JSON:
{
"DISCORD_TOKEN": "discord token",
"CHANNELS": "['channel id', 'another channel id', 'channel id etc']"
}
How to extract discord token.
Optional array CHANNELS
defines which Discord channels should be proxied.
You can remove it but it is strongly not recommended for public proxies.
Deploy secrets from local file .secrets
:
wrangler secret:bulk .secrets
Now you can test deployed proxy.
Example (adjust to include actual values): https://your-discord-cdn-proxy-url/?https://cdn.discordapp.com/attachments/channel/message/filename.ext
Debugging locally
Create .dev.vars
file with following text:
DISCORD_TOKEN="discord token"
CHANNELS=["channel id", "another channel id", "channel id etc"]
Run local development using .dev.var
secrets:
wrangler dev
Refreshing Discord links using an R2 bucket for caching
This allows you to store refreshed Discord links in a Cloudflare R2 bucket to minimize the number of calls to the Discord API.
To create an R2 bucket, execute:
wrangler r2 bucket create discord-cdn-proxy-cache
wrangler r2 bucket list
Uncomment r2_buckets
configuration in wrangler.toml
file.
Redeploy Worker:
wrangler deploy --keep-vars
Conclusion
Visit our Discord Server or Telegram Channel for any support questions and concerns.
We regularly post guides and tutorials on the YouTube Channel.
Check our GitHub repo with code examples.
Posted on May 13, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.