A structured, machine-readable map of Kleinanzeigen.de's full category tree — category / subcategory IDs, names, and parent → child relationships, three levels deep. Extracted and maintained as part of building AnzeigenBoost, a Chrome extension for Kleinanzeigen sellers.
Kleinanzeigen publishes no official API and no category reference, so anyone building tools against the platform ends up re-deriving this by hand from the "Anzeige aufgeben" form. This repo is that reference, kept current and open for anyone to use.
634 categories — 15 top-level, 143 second-level, 476 third-level.
| File | Description |
|---|---|
data/kleinanzeigen-categories.json | The full tree: numeric IDs (L1/L2), slug IDs (L3), German labels, nested subcategories. This is the one you want. |
data/kleinanzeigen-categories-names-only.json | A flat convenience view: { "L1 name": ["L2 name", …] }, two levels, no IDs. |
docs/architecture.md | High-level look at how AnzeigenBoost is built (Chrome extension + NestJS + AI layer), for anyone curious about the engineering side. |
examples/lookup-example.js | A tiny dependency-free script: flatten the tree, look up by ID, find a category path by name. |
{
"17": {
"label": "Familie, Kind & Baby",
"id": "17",
"subcategories": {
"19": {
"label": "Baby- & Kinderschuhe",
"id": "19",
"subcategories": {
"sneaker_sportschuhe": { "label": "Sneaker & Sportschuhe", "id": "sneaker_sportschuhe" }
}
}
}
}
}
"17", "19") and are globally
unique — these are the IDs Kleinanzeigen uses in its own form markup and URLs."sneaker_sportschuhe") — L3 is an attribute-style
refinement on the listing form, not a separate URL path. L3 slug IDs are
not globally unique — the same refinement repeats under many parents (e.g.
sneaker_sportschuhe appears under every shoe subcategory). Only the full
L1 → L2 → L3 path is unique.subcategories is {} for leaf L1/L2 nodes. The deepest L3 leaves omit the
key entirely ({ "label": …, "id": … }).const tree = require("./data/kleinanzeigen-categories.json");
// Flatten to a list (L3 slug ids aren't unique, so a list beats a map here)
function flatten(node, trail = [], out = []) {
for (const [id, cat] of Object.entries(node)) {
const labels = [...trail, cat.label];
out.push({ id, label: cat.label, path: labels.join(" > "), level: labels.length });
if (cat.subcategories) flatten(cat.subcategories, labels, out);
}
return out;
}
const all = flatten(tree);
// by-id lookup is reliable for L1 + L2 (unique numeric ids)
const byId = Object.fromEntries(all.filter((c) => c.level <= 2).map((c) => [c.id, c]));
byId["19"];
// { id: "19", label: "Baby- & Kinderschuhe",
// path: "Familie, Kind & Baby > Baby- & Kinderschuhe", level: 2 }
See examples/lookup-example.js for name → path
lookup and a full listing.
The IDs and labels are read directly from the live category picker on Kleinanzeigen's "Anzeige aufgeben" page. When Kleinanzeigen changes its categories, this file goes stale until someone updates it — see CONTRIBUTING.md.
Last verified: 2026-08 (see git history for the exact date of the most recent data commit).
AnzeigenBoost automates reposting, AI-optimized listings, and competitor tracking for Kleinanzeigen sellers. Free to try.
Category data goes stale as Kleinanzeigen adds and renames categories — PRs welcome to keep this accurate. See CONTRIBUTING.md.
I'm the solo developer behind AnzeigenBoost, and I'm looking for people interested in getting involved — code, product feedback, or exploring a deeper collaboration or partnership. If that sounds like you, open a Discussion or an issue and say hi.
MIT — see LICENSE. The category data is factual information about a public website and is provided as-is, with no warranty of accuracy or completeness. "Kleinanzeigen" is a trademark of its respective owner; this project is not affiliated with or endorsed by it.
1 commits
A structured, machine-readable map of Kleinanzeigen.de's full category tree — category / subcategory IDs, names, and parent → child relationships, three levels deep. Extracted and maintained as part of building AnzeigenBoost, a Chrome extension for Kleinanzeigen sellers.
Kleinanzeigen publishes no official API and no category reference, so anyone building tools against the platform ends up re-deriving this by hand from the "Anzeige aufgeben" form. This repo is that reference, kept current and open for anyone to use.
634 categories — 15 top-level, 143 second-level, 476 third-level.
| File | Description |
|---|---|
data/kleinanzeigen-categories.json | The full tree: numeric IDs (L1/L2), slug IDs (L3), German labels, nested subcategories. This is the one you want. |
data/kleinanzeigen-categories-names-only.json | A flat convenience view: { "L1 name": ["L2 name", …] }, two levels, no IDs. |
docs/architecture.md | High-level look at how AnzeigenBoost is built (Chrome extension + NestJS + AI layer), for anyone curious about the engineering side. |
examples/lookup-example.js | A tiny dependency-free script: flatten the tree, look up by ID, find a category path by name. |
{
"17": {
"label": "Familie, Kind & Baby",
"id": "17",
"subcategories": {
"19": {
"label": "Baby- & Kinderschuhe",
"id": "19",
"subcategories": {
"sneaker_sportschuhe": { "label": "Sneaker & Sportschuhe", "id": "sneaker_sportschuhe" }
}
}
}
}
}
"17", "19") and are globally
unique — these are the IDs Kleinanzeigen uses in its own form markup and URLs."sneaker_sportschuhe") — L3 is an attribute-style
refinement on the listing form, not a separate URL path. L3 slug IDs are
not globally unique — the same refinement repeats under many parents (e.g.
sneaker_sportschuhe appears under every shoe subcategory). Only the full
L1 → L2 → L3 path is unique.subcategories is {} for leaf L1/L2 nodes. The deepest L3 leaves omit the
key entirely ({ "label": …, "id": … }).const tree = require("./data/kleinanzeigen-categories.json");
// Flatten to a list (L3 slug ids aren't unique, so a list beats a map here)
function flatten(node, trail = [], out = []) {
for (const [id, cat] of Object.entries(node)) {
const labels = [...trail, cat.label];
out.push({ id, label: cat.label, path: labels.join(" > "), level: labels.length });
if (cat.subcategories) flatten(cat.subcategories, labels, out);
}
return out;
}
const all = flatten(tree);
// by-id lookup is reliable for L1 + L2 (unique numeric ids)
const byId = Object.fromEntries(all.filter((c) => c.level <= 2).map((c) => [c.id, c]));
byId["19"];
// { id: "19", label: "Baby- & Kinderschuhe",
// path: "Familie, Kind & Baby > Baby- & Kinderschuhe", level: 2 }
See examples/lookup-example.js for name → path
lookup and a full listing.
The IDs and labels are read directly from the live category picker on Kleinanzeigen's "Anzeige aufgeben" page. When Kleinanzeigen changes its categories, this file goes stale until someone updates it — see CONTRIBUTING.md.
Last verified: 2026-08 (see git history for the exact date of the most recent data commit).
AnzeigenBoost automates reposting, AI-optimized listings, and competitor tracking for Kleinanzeigen sellers. Free to try.
Category data goes stale as Kleinanzeigen adds and renames categories — PRs welcome to keep this accurate. See CONTRIBUTING.md.
I'm the solo developer behind AnzeigenBoost, and I'm looking for people interested in getting involved — code, product feedback, or exploring a deeper collaboration or partnership. If that sounds like you, open a Discussion or an issue and say hi.
MIT — see LICENSE. The category data is factual information about a public website and is provided as-is, with no warranty of accuracy or completeness. "Kleinanzeigen" is a trademark of its respective owner; this project is not affiliated with or endorsed by it.
1 commits