An open-source serverless API (Vercel + Go) for public Duolingo profile data — REST endpoints, a shields.io-compatible endpoint, and ready-to-embed SVG badges for your README.
Enter a Duolingo username to see the API's real response and the generated badges.
All routes return JSON and require the username query parameter. Base URL: https://your-instance.vercel.app
curl "https://your-instance.vercel.app/api/user?username=duome"
{
"username": "duome",
"name": "Duome",
"streak": 12,
"totalXp": 93,
"crownsTotal": 41,
"coursesCount": 2,
"xpByLanguage": [ { "language_id": "...", "percentage": 63.4 } ]
}
startDate/endDate)./api/shields returns the JSON schema that shields.io's dynamic endpoint badge expects — useful if you already use shields.io elsewhere in your README and want a consistent look.
| Parameter | Required | Description |
|---|---|---|
username | yes | Duolingo username |
stat | no | streak (default), xp, crowns, courses, or name |
label | no | Overrides the left-hand label text |
color | no | Overrides the color (shields.io name or hex) |
https://img.shields.io/endpoint?url=https://your-instance.vercel.app/api/shields?username=duome%26stat=streak
In Markdown:

/api/badge renders the SVG directly — simpler to embed, with no extra round trip through shields.io.
| Parameter | Required | Description |
|---|---|---|
username | yes | Duolingo username |
stat | no | streak (default), xp, crowns, courses, name |
label | no | Overrides the left-hand label text |
color | no | Shields.io color name (brightgreen, orange, blue...) or hex (#ff69b4) |
style | no | flat (default) or flat-square |
/api/badge?username=duome&stat=streak
In Markdown:

/api/user, /api/stats...)username or a user that doesn't exist → 400/404 with { "error": "..." }. Cache: max-age=300./api/shields and /api/badge200 with a red error badge/JSON, so the embedded README image never breaks. Cache: max-age=3600.