Slugify API: turn any title into a clean URL slug
Turn "Héllo, World’s Best Café!" into hello-worlds-best-cafe. Slugs are the readable part of a web address, and getting them consistent matters for links that should never change.
/v1/slug?text=H%C3%A9llo,%20World%E2%80%99s%20Best%20Caf%C3%A9%21 returns JSON. No key, CORS on, 60 requests a minute./v1/slug
Turn a title into a clean URL slug. Change the values and press Send request to call the live API.
Parameters
| Name | Type | What it does | Default |
|---|---|---|---|
text required | string | Up to 4 KB | — |
sep | string | Separator: - or _ | - |
max | integer | Max length 1–200 | 80 |
Example
Request:
GET https://api.oddlathe.com/v1/slug?text=H%C3%A9llo,%20World%E2%80%99s%20Best%20Caf%C3%A9%21
Response (generated by the real code when these docs were last built):
{
"slug": "hello-worlds-best-cafe"
}
Code examples
curl -G 'https://api.oddlathe.com/v1/slug' \
--data-urlencode 'text=Héllo, World’s Best Café!'const params = new URLSearchParams({
text: "Héllo, World’s Best Café!"
});
const res = await fetch(`https://api.oddlathe.com/v1/slug?${params}`);
if (!res.ok) throw new Error((await res.json()).error.message);
const data = await res.json();
console.log(data);import json, urllib.parse, urllib.request
params = urllib.parse.urlencode({"text": "Héllo, World’s Best Café!"})
url = "https://api.oddlathe.com/v1/slug?" + params
# Send a User-Agent: the edge network refuses Python's default one.
req = urllib.request.Request(url, headers={"User-Agent": "my-script/1.0"})
with urllib.request.urlopen(req, timeout=10) as r:
data = json.load(r)
print(data)When it's useful
- URLs for blog posts, products or docs pages
- Safe file names from user-supplied titles
- Anchor IDs for headings
Good to know
- Letters with accents are folded to their base letter using Unicode decomposition (é → e, ñ → n).
- Characters with no plain-letter form are dropped, for example ß, ø, ł, emoji and non-Latin scripts. Transliterate first if you need those.
- Runs of anything that isn't a letter or digit become one separator, trimmed from both ends. A cut at
maxnever leaves a trailing separator.
Accents are folded to plain letters (é → e), apostrophes dropped, everything else that isn't a letter or digit becomes the separator.
Errors
Errors are JSON like {"error": {"code": "…", "message": "…"}}. The ones this endpoint can return:
missing_param(400): a required parameter is missing or emptybad_param(400): a value is the wrong type or out of range (the message says which)too_long(413): text is over 4 KBrate_limited(429): over 60 requests a minute; wait for Retry-After seconds
Questions
Why is the apostrophe dropped instead of becoming a hyphen?
So that world’s becomes worlds rather than world-s, which reads better.
Will the same title always give the same slug?
Yes, it's deterministic. Responses are cacheable for that reason.
Related endpoints
Prefer a page to an API?
- Case converter (kebab, snake, camel and more) on Tooltern: same job, nothing leaves your browser.
Published · OpenAPI 3.1 spec · Limits and privacy