LangPop API v1
Free. Public. JSON.
Five read endpoints for programming language rankings, history, and our scoring methodology. No auth, open CORS, updated weekly.
Quickstart
Fetch the latest top 5 languages:
$ curl https://langpop.com/api/v1/rankings?limit=5Returns JSON. Pipe it through jq to slice it: curl … | jq '.data[].language'.
Conventions
- Base URL:
https://langpop.com - Versioning: All endpoints live under
/api/v1/. Breaking changes ship as/api/v2/; both run in parallel for at least 6 months before sunset. - Auth: None. The public surface is free, no API key required.
- CORS:
Access-Control-Allow-Origin: *on every endpoint — fetch directly from browser JavaScript. - Caching:
Cache-Control: public, max-age=3600, s-maxage=3600. Data refreshes weekly so 1h CDN cache is generous. - Version header: Every v1 response carries
X-LangPop-Version: v1so you can detect contract drift. - Rate limits: Not enforced today. We're sizing this against real traffic; expect
~60 req/min/IPwithX-RateLimit-*headers when limits go live. Be reasonable. - Attribution: Free to use with attribution to langpop.com. The license string is in every
metablock.
Response envelope
Every successful response follows this shape:
{
"meta": {
"source": "LangPop",
"url": "https://langpop.com",
"version": "v1",
"generated_at": "2026-05-24T08:00:00.000Z",
"license": "Free to use with attribution to langpop.com"
},
"data": /* endpoint-specific payload */
}Endpoints that return a snapshot for a specific week also include meta.week_start (ISO date, always a Monday).
Errors
Errors return a single error object — never a stack trace, never an internal Supabase message.
{
"error": {
"code": "invalid_param",
"message": "limit must be between 1 and 50"
}
}| HTTP | error.code | When |
|---|---|---|
| 400 | invalid_param | Query param failed validation. |
| 404 | not_found | Slug or week doesn't exist in the dataset. |
| 429 | rate_limited | Rate limit exceeded (when limits ship — see Conventions). |
| 500 | internal_error | Something on our side. Please report repeated 500s. |
| 503 | unavailable | Downstream (database) is unreachable. |
Endpoints
/api/v1/rankingsThe latest weekly ranking snapshot. The workhorse endpoint.
Parameters
| Name | Type | Default | Notes |
|---|---|---|---|
| week | ISO date (YYYY-MM-DD) | latest | Must be a Monday matching a week in our dataset. 404 if no rows. |
| limit | integer 1–50 | 20 | We currently track 20 languages, so 20 is the natural cap. |
| source | enum | — | github | jobs | stackoverflow | trends | packages | reddit | tutorials. If set, the array is re-sorted by that source's score (composite rank field is unchanged). |
Example
$ curl https://langpop.com/api/v1/rankings?limit=3Sample response
{
"meta": {
"source": "LangPop",
"url": "https://langpop.com",
"version": "v1",
"generated_at": "2026-05-24T08:00:00.000Z",
"license": "Free to use with attribution to langpop.com",
"week_start": "2026-05-19"
},
"data": [
{
"rank": 1,
"language": "Python",
"slug": "python",
"composite_score": 48.64,
"github_score": 100.0,
"jobs_score": 92.4,
"stackoverflow_score": 88.1,
"trends_score": 95.2,
"packages_score": 84.7,
"reddit_score": 0,
"tutorials_score": 76.5,
"previous_rank": 1,
"week_start": "2026-05-19"
},
{
"rank": 2,
"language": "JavaScript",
"slug": "javascript",
"composite_score": 39.70,
"github_score": 91.3,
"jobs_score": 88.0,
"stackoverflow_score": 81.2,
"trends_score": 78.9,
"packages_score": 96.1,
"reddit_score": 0,
"tutorials_score": 72.4,
"previous_rank": 2,
"week_start": "2026-05-19"
},
{
"rank": 3,
"language": "TypeScript",
"slug": "typescript",
"composite_score": 33.21,
"github_score": 85.4,
"jobs_score": 79.7,
"stackoverflow_score": 60.1,
"trends_score": 64.2,
"packages_score": 71.8,
"reddit_score": 0,
"tutorials_score": 55.0,
"previous_rank": 4,
"week_start": "2026-05-19"
}
]
}previous_rank is null when this is the first week the language appeared in the dataset.
reddit_score: 0 in the sample above is real: the Reddit collector is awaiting API credentials, so all 20 languages currently get 0 for that source. The composite weighting effectively drops Reddit until the collector backfills.
/api/v1/language/:slugA single language: metadata, current rank with all seven source scores, optional history.
Parameters
| Name | Type | Default | Notes |
|---|---|---|---|
| slug* | path, lowercase | — | e.g. python, javascript, rust. Must match languages.slug. 404 if not tracked. |
| history | integer 0–52 | 12 | Number of historical weeks to include (oldest -> newest). 0 omits history. |
Example
$ curl https://langpop.com/api/v1/language/python?history=3Sample response
{
"meta": {
"source": "LangPop",
"url": "https://langpop.com",
"version": "v1",
"generated_at": "2026-05-24T08:00:00.000Z",
"license": "Free to use with attribution to langpop.com",
"week_start": "2026-05-19"
},
"data": {
"slug": "python",
"name": "Python",
"description": "High-level, general-purpose, dynamically typed.",
"paradigms": ["multi-paradigm", "object-oriented", "functional"],
"created_year": 1991,
"creator": "Guido van Rossum",
"website": "https://www.python.org",
"current": {
"rank": 1,
"language": "Python",
"slug": "python",
"composite_score": 48.64,
"github_score": 100.0,
"jobs_score": 92.4,
"stackoverflow_score": 88.1,
"trends_score": 95.2,
"packages_score": 84.7,
"reddit_score": 0,
"tutorials_score": 76.5,
"previous_rank": 1,
"week_start": "2026-05-19"
},
"history": [
{ "week_start": "2026-05-05", "rank": 1, "composite_score": 47.82 },
{ "week_start": "2026-05-12", "rank": 1, "composite_score": 48.10 },
{ "week_start": "2026-05-19", "rank": 1, "composite_score": 48.64 }
]
}
}/api/v1/languagesEvery language we track, with current rank. Useful for building dropdowns and filters without fetching the full ranking payload.
Parameters
No parameters.
Example
$ curl https://langpop.com/api/v1/languagesSample response
{
"meta": {
"source": "LangPop",
"url": "https://langpop.com",
"version": "v1",
"generated_at": "2026-05-24T08:00:00.000Z",
"license": "Free to use with attribution to langpop.com"
},
"data": [
{
"slug": "python",
"name": "Python",
"current_rank": 1,
"created_year": 1991,
"creator": "Guido van Rossum",
"paradigms": ["multi-paradigm", "object-oriented", "functional"]
},
{
"slug": "javascript",
"name": "JavaScript",
"current_rank": 2,
"created_year": 1995,
"creator": "Brendan Eich",
"paradigms": ["multi-paradigm", "event-driven", "functional"]
}
/* … */
]
}/api/v1/weeksEvery week for which we have ranking data, newest first. Use this to build a historical picker.
Parameters
No parameters.
Example
$ curl https://langpop.com/api/v1/weeksSample response
{
"meta": {
"source": "LangPop",
"url": "https://langpop.com",
"version": "v1",
"generated_at": "2026-05-24T08:00:00.000Z",
"license": "Free to use with attribution to langpop.com"
},
"data": [
"2026-05-19",
"2026-05-12",
"2026-05-05",
"2026-04-28"
/* … */
]
}/api/v1/methodologyProgrammatic methodology — source list, weights, and the composite formula. Lets a determined consumer reproduce our number from raw inputs.
Parameters
No parameters.
Example
$ curl https://langpop.com/api/v1/methodologySample response
{
"meta": {
"source": "LangPop",
"url": "https://langpop.com",
"version": "v1",
"generated_at": "2026-05-24T08:00:00.000Z",
"license": "Free to use with attribution to langpop.com"
},
"data": {
"sources": [
{ "code": "github", "name": "GitHub", "weight": 0.25, "frequency": "daily", "description": "Active repos, stars, forks, commits." },
{ "code": "jobs", "name": "Job Postings", "weight": 0.20, "frequency": "weekly", "description": "Aggregated job listings." },
{ "code": "stackoverflow", "name": "Stack Overflow", "weight": 0.15, "frequency": "weekly", "description": "Questions, answers, tag activity." },
{ "code": "trends", "name": "Google Trends", "weight": 0.15, "frequency": "weekly", "description": "Search interest, normalized." },
{ "code": "packages", "name": "Package Mgrs", "weight": 0.10, "frequency": "weekly", "description": "npm / PyPI / crates.io downloads." },
{ "code": "reddit", "name": "Reddit", "weight": 0.10, "frequency": "weekly", "description": "Subreddit activity." },
{ "code": "tutorials", "name": "Tutorials", "weight": 0.05, "frequency": "weekly", "description": "Course enrollment data." }
],
"formula": "weighted_sum / total_weight"
}
}Full prose methodology with caveats and known limitations lives on /methodology. The endpoint is the machine-readable version of that page.
Stability + license
v1 is a frozen contract. Adding new optional fields to a response is fine; removing or renaming anything is a breaking change and ships as /api/v2/.
License: free to use with attribution. If you publish a chart, table, or article using LangPop data, credit langpop.com and link back. Suggested phrasing lives on /press.
Bugs: Email hello@langpop.com with the request URL and what you expected. We're a small team — replies in days, not minutes.
Changelog
v1.0 — Launch
2026-05-24
- Five read endpoints:
/rankings,/language/:slug,/languages,/weeks,/methodology. - Open CORS, no auth, 1h cache headers.
- Response envelope:
{ meta, data }. Errors:{ error: { code, message } }.