duoinfo-api

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.

streak badge xp badge crowns badge

Try it now

Enter a Duolingo username to see the API's real response and the generated badges.

GET API routes

All routes return JSON and require the username query parameter. Base URL: https://your-instance.vercel.app

GET/api/user?username=<user>

Full profile: name, bio, picture, streak, total XP, courses, and XP by language.
curl "https://your-instance.vercel.app/api/user?username=duome"

GET/api/stats?username=<user>

Compact summary: streak, total XP, total crowns (summed across every course), and course count.
{
  "username": "duome",
  "name": "Duome",
  "streak": 12,
  "totalXp": 93,
  "crownsTotal": 41,
  "coursesCount": 2,
  "xpByLanguage": [ { "language_id": "...", "percentage": 63.4 } ]
}

GET/api/streak

Current streak and its interval (startDate/endDate).

GET/api/xp

Total XP and the percentage breakdown by language/course.

GET/api/courses

Enrolled courses: title, languages, XP, and crowns.

Shields.io integration

/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.

GET/api/shields?username=<user>&stat=<stat>

ParameterRequiredDescription
usernameyesDuolingo username
statnostreak (default), xp, crowns, courses, or name
labelnoOverrides the left-hand label text
colornoOverrides 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:

![Duolingo streak](https://img.shields.io/endpoint?url=https://your-instance.vercel.app/api/shields?username=duome%26stat=streak)

SVG badges (no shields.io dependency)

/api/badge renders the SVG directly — simpler to embed, with no extra round trip through shields.io.

GET/api/badge?username=<user>&stat=<stat>

ParameterRequiredDescription
usernameyesDuolingo username
statnostreak (default), xp, crowns, courses, name
labelnoOverrides the left-hand label text
colornoShields.io color name (brightgreen, orange, blue...) or hex (#ff69b4)
stylenoflat (default) or flat-square
badge preview /api/badge?username=duome&stat=streak

In Markdown:

![Duolingo streak](https://your-instance.vercel.app/api/badge?username=duome&stat=streak)

Errors & caching

JSON routes (/api/user, /api/stats...)

Missing username or a user that doesn't exist → 400/404 with { "error": "..." }. Cache: max-age=300.

/api/shields and /api/badge

Never return an HTTP error — always 200 with a red error badge/JSON, so the embedded README image never breaks. Cache: max-age=3600.