🍔 burg.nr
API docs. Create short links with one request. No API key and no sign-up.
Create a link
POST https://burg.nr/api/shorten
| Field | Description |
|---|---|
url | Required. The long link. If you leave out https://, it's added for you. |
alias | Optional. Your own ending: 3 to 32 letters, numbers, - or _. Case sensitive. Leave it out for a random one. |
Send JSON with Content-Type: application/json. Regular form data works too.
Response
A new link returns status 201:
{
"ok": true,
"code": "abc12",
"short": "https://burg.nr/abc12",
"url": "https://example.com/very/long/link"
}
Errors return {"ok":false,"error":"..."} with one of these statuses:
400 | Bad URL, or an invalid or reserved alias. |
405 | Wrong HTTP method. Creating a link needs POST, and the other endpoints need GET. |
409 | That alias is already taken. |
429 | Rate limit reached. Try again later. |
500 | Server error. |
Get link info and clicks
GET https://burg.nr/api/link/{code}
Returns where a link goes, how many times it has been clicked, and when it was created (server time). An unknown code returns status 404.
{
"ok": true,
"code": "abc12",
"short": "https://burg.nr/abc12",
"url": "https://example.com/very/long/link",
"clicks": 42,
"created_at": "2026-11-14 09:30:00"
}
Every visit counts as a click, including bots and link previews.
Site stats
GET https://burg.nr/api/stats
Totals for the whole site. today counts links made in the last 24 hours.
{ "ok": true, "links": 1240, "clicks": 8431, "today": 12 }
Examples
curl
curl -X POST https://burg.nr/api/shorten \
-H "Content-Type: application/json" \
-d '{"url":"example.com/very/long/link","alias":"my-link"}'
curl https://burg.nr/api/link/my-link
curl https://burg.nr/api/stats
Node.js 18+ or browser
const res = await fetch('https://burg.nr/api/shorten', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url: 'example.com/very/long/link' }),
});
const data = await res.json();
console.log(data.ok ? data.short : data.error);
// Get the click count
const info = await (await fetch(`https://burg.nr/api/link/${data.code}`)).json();
console.log(info.clicks);
Python
import requests
r = requests.post('https://burg.nr/api/shorten',
json={'url': 'example.com/very/long/link'})
data = r.json()
print(data['short'] if data['ok'] else data['error'])
# Get the click count
info = requests.get(f"https://burg.nr/api/link/{data['code']}").json()
print(info['clicks'])
Discord bots
Two small bots with /shorten and /clicks slash commands. Put your bot token in a DISCORD_TOKEN environment variable instead of the code.
Node.js with discord.js v14 (Node 18 or newer, npm i discord.js)
const { Client, GatewayIntentBits, SlashCommandBuilder } = require('discord.js');
const API = 'https://burg.nr/api';
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.once('ready', () => {
client.application.commands.set([
new SlashCommandBuilder().setName('shorten').setDescription('Shorten a link')
.addStringOption(o => o.setName('url').setDescription('The long link').setRequired(true))
.addStringOption(o => o.setName('alias').setDescription('Custom ending')),
new SlashCommandBuilder().setName('clicks').setDescription('Get the clicks on a short link')
.addStringOption(o => o.setName('code').setDescription('The short code').setRequired(true)),
]);
});
client.on('interactionCreate', async (i) => {
if (!i.isChatInputCommand()) return;
await i.deferReply();
if (i.commandName === 'shorten') {
const res = await fetch(`${API}/shorten`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
url: i.options.getString('url'),
alias: i.options.getString('alias') || undefined,
}),
});
const d = await res.json();
return i.editReply(d.ok ? `🍔 ${d.short}` : `Couldn't shorten: ${d.error}`);
}
if (i.commandName === 'clicks') {
const code = encodeURIComponent(i.options.getString('code'));
const d = await (await fetch(`${API}/link/${code}`)).json();
return i.editReply(d.ok ? `${d.short} has ${d.clicks} clicks.` : `Error: ${d.error}`);
}
});
client.login(process.env.DISCORD_TOKEN);
Python with discord.py (Python 3.10 or newer, pip install discord.py aiohttp)
import os
from urllib.parse import quote
import aiohttp
import discord
from discord import app_commands
API = 'https://burg.nr/api'
class Bot(discord.Client):
def __init__(self):
super().__init__(intents=discord.Intents.default())
self.tree = app_commands.CommandTree(self)
async def setup_hook(self):
await self.tree.sync()
bot = Bot()
@bot.tree.command(description='Shorten a link')
async def shorten(interaction: discord.Interaction, url: str, alias: str | None = None):
await interaction.response.defer()
payload = {'url': url}
if alias:
payload['alias'] = alias
async with aiohttp.ClientSession() as s:
async with s.post(f'{API}/shorten', json=payload) as r:
d = await r.json()
await interaction.followup.send(f"🍔 {d['short']}" if d['ok'] else f"Couldn't shorten: {d['error']}")
@bot.tree.command(description='Get the clicks on a short link')
async def clicks(interaction: discord.Interaction, code: str):
await interaction.response.defer()
async with aiohttp.ClientSession() as s:
async with s.get(f'{API}/link/{quote(code)}') as r:
d = await r.json()
await interaction.followup.send(f"{d['short']} has {d['clicks']} clicks." if d['ok'] else f"Error: {d['error']}")
bot.run(os.environ['DISCORD_TOKEN'])
Rate limits apply per IP address, so everyone using your bot shares one limit.
Limits and rules
Each IP address can create 60 links per hour through the API. Only http and https links work, and links to burg.nr itself or to private addresses are blocked.
The same acceptable use rules as the website apply. No spam, phishing, malware, or scams. Abusive links are removed, and abusers may be blocked.