Around 800 curated language-learning resources across 30+ languages, as JSON and CSV: apps, courses, podcasts, YouTube channels, books, dictionaries, tools and communities — each with honest notes and machine-readable facets (type, CEFR, level, skills, method, price).
A list of links is a bookmark folder. This is meant to answer "what should I use, at my level, for this language" — and to stay queryable while it does.
The data behind howtolearn.app, under CC BY 4.0.
The whole dataset as pages you can read on GitHub, one per language — with the notes and the caveats, not just the links: catalog/ · Spanish · Japanese · French · all 33 languages
One table per language holding every field: type, level, CEFR, price, skills,
method, platform links, pitch and the full notes. Facets first so they stay on
screen; the prose columns are at the end, since those are the ones you read
rather than scan. Generated by node scripts/catalog.mjs — corrections go to
data/resources/, never to the Markdown.
| File | What it is |
|---|---|
resources.json |
every resource in one array |
resources.csv |
one row per resource, for spreadsheets |
data/resources/*.json |
the source of truth, one file per language |
The root files are generated and committed, so nothing needs building. After
editing data/, regenerate with node scripts/build.mjs — plain Node, no
dependencies. Exact counts live in stats.json; the numbers above
are approximate on purpose, so they cannot go stale here.
A record, trimmed:
{
"language": "spanish",
"id": "notes-in-spanish",
"name": "Notes in Spanish",
"url": "https://www.notesinspanish.com/",
"types": ["podcast", "course"],
"levels": ["beginner", "intermediate", "advanced"],
"cefr": "A1–C1",
"skills": ["listening", "vocabulary", "speaking"],
"price": "freemium",
"methods": ["comprehensible-input"],
"pitch": "Unscripted conversations between Ben and Marina, graded across three clear levels.",
"notes": "… the audio is free; worksheets and transcripts are sold as paid packs, which is the main catch …",
"links": [{ "label": "Apple Podcasts", "url": "https://podcasts.apple.com/…" }]
}Free podcasts a beginner can start with, in any language:
jq -r '.[] | select((.types | index("podcast")) and .price == "free"
and (.levels | index("beginner")))
| [.language, .name, .url] | @tsv' resources.jsonEvery RSS feed, one per line — a ready-made podcast OPML source:
jq -r '.[] | .links[]? | select(.label == "RSS") | .url' resources.jsonEverything teaching Japanese through comprehensible input:
import json
rows = json.load(open("resources.json"))
[r["name"] for r in rows
if r["language"] == "japanese" and "comprehensible-input" in r.get("methods", [])]More recipes, the CSV columns and the full record: docs/usage.md.
- Schema — every field, type and allowed value
- What is in it — counts by type, method and language
- Using the data — recipes, CSV columns, repo layout
- How it was curated — selection, link verification, link check
- Limitations — what the data is not, and known issues
- Contributing — corrections are the main thing this repo wants
Data — CC BY 4.0. Use it commercially, remix it, build on it;
attribution is the one requirement. Code (scripts/) — MIT.
Language learning resources dataset, curated by How to Learn, licensed CC BY 4.0.