A Free URL Shortener API With No Authentication
POST a long URL, get a short one back. No API key, no account, no monthly quota — just an HTTP request from cURL, Python, JavaScript, Go, or anything else that speaks JSON.
Quick start
Pick a language and run it. There is no authentication step — the request below is the entire integration.
curl -X POST http://zip1.io/api/create \
-H "Content-Type: application/json" \
-d '{"url": "https://your-long-url.com/some/very/deep/path"}'
import requests
response = requests.post(
"http://zip1.io/api/create",
json={"url": "https://your-long-url.com/some/very/deep/path"},
)
print(response.json()["short_url"]) # http://zip1.io/abc123
const response = await fetch("http://zip1.io/api/create", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ url: "https://your-long-url.com/some/very/deep/path" })
});
const data = await response.json();
console.log(data.short_url); // http://zip1.io/abc123
package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
body := []byte(`{"url": "https://your-long-url.com/some/very/deep/path"}`)
resp, err := http.Post("http://zip1.io/api/create", "application/json", bytes.NewBuffer(body))
if err != nil {
panic(err)
}
defer resp.Body.Close()
data, _ := io.ReadAll(resp.Body)
fmt.Println(string(data))
}
A successful request returns HTTP 200 with the short URL and creation timestamp:
{
"short_url": "http://zip1.io/abc123",
"created_at": "2026-07-06T12:00:00+00:00"
}
Every option in one request — a branded slug that dies after 100 clicks, expires at year end, and asks visitors for a password:
curl -X POST http://zip1.io/api/create \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-long-url.com/campaign",
"alias": "spring-launch",
"max-clicks": 100,
"expiration-time": "2026-12-31T23:59:00Z",
"password": "open.sesame1",
"description": "Spring launch — email cohort A"
}'
Endpoints
| Endpoint | Rate limit (per IP) | What it does |
|---|---|---|
POST /api/create |
10 / minute | Create a short link |
GET /api/stats/<code> |
30 / minute | Click stats as JSON |
GET /api/check-alias?alias=<slug> |
60 / minute | Check if a custom slug is free |
GET /export/<code>/<format> |
— | Export click data as csv, json, xlsx, or xml |
Parameters for POST /api/create
| Field | Required | Rules |
|---|---|---|
url |
Required | A valid http(s) URL — the redirect destination |
alias |
Optional | Custom slug, up to 12 characters: letters, numbers, -, _ |
password |
Optional | 8+ characters with a letter, a number, and @ or . |
max-clicks |
Optional | Positive integer — the link stops redirecting after N clicks |
expiration-time |
Optional | ISO 8601 with timezone, at least 5 minutes ahead (e.g. 2026-12-31T23:59:00Z) |
description |
Optional | Label of up to 100 characters, shown on the stats page |
Stats response
GET /api/stats/<code> returns totals, uniques, and top countries for any short link — no ownership check, no token:
{
"message": "Statistics retrieved successfully",
"data": {
"short_code": "spring-launch",
"total_clicks": 87,
"unique_clicks": 64,
"creation_date": "2026-07-06T12:00:00+00:00",
"last_click": "2026-07-06T15:42:11+00:00",
"click_limit": "100",
"expiration_time": "2026-12-31T23:59:00+00:00",
"is_password_protected": true,
"top_countries": [{"country": "United States", "clicks": 31}],
"recent_clicks": []
}
}
Need spreadsheets instead? The same analytics export as CSV, XLSX, JSON, or XML via /export/<code>/<format>.
Rate limits
Because there are no API keys, limits apply per IP address: 10 link creations per minute, 30 stats reads per minute, 60 alias checks per minute. There is no daily or monthly quota — create as many links over time as you need. The limits exist to stop abuse, not to sell an upgrade.
Exceed a limit and you get HTTP 429:
{"error": "ratelimit exceeded 10 per 1 minute"}
Back off until the minute window resets and retry. If you legitimately need more throughput, get in touch.
Error responses
Errors return a JSON body with a message field and a conventional status code — except 429, where the rate limiter responds with an error field:
| Status | When | Example message |
|---|---|---|
400 |
Missing or malformed url |
"Invalid URL format or missing required fields" |
400 |
Invalid alias, password, max-clicks, expiration-time, or description |
"max-clicks must be a positive integer" |
403 |
Destination is on the abuse blocklist | "URL is blocked" |
409 |
Requested alias is already taken | "Alias already exists" |
404 |
Stats requested for an unknown short code | "Short link not found" |
429 |
Rate limit exceeded | {"error": "ratelimit exceeded 10 per 1 minute"} |
How it compares to the bit.ly and TinyURL APIs
Most URL shortener APIs assume an account, an access token, and a plan. If you just need short links from a script, a CI job, or an AI agent, that setup is the slowest part. Here's the honest comparison:
| Capability | zip1.io API | bit.ly API | TinyURL API |
|---|---|---|---|
| Authentication | None | Account + OAuth token | Account + API token |
| Monthly link quota | None — rate limit only | Capped on the free plan | Capped on the free plan |
| Custom slugs via API, free | Yes | Limited on free plan | Limited on free plan |
| Password-protected links | Yes, free | Not offered | Not offered |
Click caps (max-clicks) |
Yes | No | No |
| Click analytics via API, free | Yes | Limited free tier | Paid plans |
| Signup required | No | Yes | Yes |
Plan details for bit.ly and TinyURL are as published on their pricing pages and may change. The structural difference is stable: both authenticate every request and meter link creation by plan; zip1.io does neither.
Built for AI agents too
The same API is exposed as a Model Context Protocol server, so agents like Claude can mint and track short links as native tools instead of raw HTTP calls:
claude mcp add --transport http zip1 http://zip1.io/mcp
No key to provision for the agent either — the no-auth design is what makes zero-config agent integration possible.
FAQ
-
Do I need an API key?
No. Zero authentication — no API key, no OAuth token, no account. Send a POST request to
/api/createand you get a short URL back. Rate limiting is per IP address instead of per key. -
Is the API free, and what are the rate limits?
Free, with no paid tier and no monthly link quota. Limits are per IP: 10 link creations per minute, 30 stats requests per minute, 60 alias checks per minute. Exceeding one returns HTTP 429 until the window resets.
-
Can I set a custom slug through the API?
Yes, and it's free. Pass an
aliasfield — up to 12 characters: letters, numbers, hyphens, underscores. Taken aliases return HTTP 409; pre-check availability withGET /api/check-alias. -
What options does /api/create support besides the URL?
alias(custom slug),password(visitors must enter it before redirecting),max-clicks(link stops working after N clicks),expiration-time(ISO 8601 timestamp when the link dies), anddescription(a label of up to 100 characters shown on the stats page). -
Is zip1.io a bit.ly API alternative?
For programmatic link creation, yes. The bit.ly API needs an account and an OAuth token, and its free plan caps monthly link creation. zip1.io needs no token, has no monthly quota, and includes custom slugs, click caps, and password protection for free.
Related
Ship your integration in five minutes
The full reference covers every endpoint, parameter, and response schema — or skip the reading and send your first request now.