Free-Tarif

Lebensmittel-Datenbank API

Eine einzige Quelle für 6,1 Millionen Lebensmittel. Hole einen vollständigen Produktdatensatz per ID — Name, Marke, Zutaten, Allergene, Nutri-Score, NOVA-Gruppe, Bilder und mehr.

200 OK
GET /v1/foods/{id}
curl -H "X-API-Key: food_•••" \
  "https://foodbase.dev/v1/foods/62ea12b8-b260-c288-5c38-3a4906f5d6dd"

{
  "id": "62ea12b8-b260-c288-5c38-3a4906f5d6dd",
  "name_default": "Original Taste",
  "brand": "Coca-Cola",
  "category": "...,Carbonated drinks,Sodas,Colas",
  "ingredients_default": "carbonated water, sugar, ...",
  "allergens": null,
  "nutriscore": "e",
  "nova_group": 4,
  "image_url": "https://images..."
}

Lieber klicken? Probier den Produkt-Explorer oder die Foto-Spielwiese aus.

Was du zurückbekommst

Identität

id, barcode, source, name, brand, category.

Zutaten

Vollständiger Zutatentext plus strukturierte Allergene und Spuren.

Bewertungen

Nutri-Score, NOVA-Gruppe und Eco-Score, sofern verfügbar.

Medien & Sprache

Produktbild-URL und mehrsprachige Namen.

Ein Schema

Jedes Produkt normalisiert in eine einheitliche Form.

Im kostenlosen Tarif enthalten — 100 Anfragen/Tag, keine Kreditkarte nötig. Tarife ansehen →

Codebeispiele

Dieselbe Anfrage in curl, JavaScript und Python. Ersetze YOUR_API_KEY durch einen Schlüssel aus deinem Dashboard.


              curl "https://foodbase.dev/v1/foods/62ea12b8-b260-c288-5c38-3a4906f5d6dd?lang=fr" \
  -H "X-API-Key: YOUR_API_KEY"
            

So funktioniert's

Was eine Anfrage macht

GET /v1/foods/{id} nimmt die UUID, die du aus einer Suche oder Barcode-Abfrage erhalten hast, und liefert den gesamten normalisierten Datensatz. Es gibt keine Feldauswahl und keine Paginierung: Der Datensatz für 62ea12b8-b260-c288-5c38-3a4906f5d6dd (Barcode 5449000000996, source openfoodfacts) kommt mit jedem Schlüssel des 200-Schemas zurück, und was die Quelle nicht hat, ist null statt weggelassen.

Authentifiziere dich mit dem X-API-Key-Header. Die einzige optionale Eingabe ist ?lang=, eines von en, fr, es, de, it oder bg. Es hängt category_localized, category_segments_localized und allergens_localized an und lässt alle anderen Schlüssel unberührt — ein späteres Hinzufügen von lang bricht also keinen bestehenden Parser. Jede Antwort trägt außerdem einen X-Request-Id-Header, den du in Support-Anfragen nennen kannst.

Namen, Zutaten und der Haupteintrag

name und ingredients sind Arrays aus {lang, text}. Der erste Eintrag hat lang main und spiegelt name_default und ingredients_default; product_lang sagt dir, welche echte Sprache das ist. Beim Coca-Cola-Datensatz ist der Hauptname Original Taste, der fr-Eintrag lautet Coca-Cola en canette und der bg-Eintrag Кока-Кола. Wähle den Eintrag passend zu deiner UI-Sprache und falle auf name_default zurück.

Rechne damit, dass ingredients länger ist als die Zahl der Sprachen: Open Food Facts speichert den Zutatentext pro Verpackungsvariante, sodass dieselbe lang mehrmals in einem Datensatz vorkommen kann, oft mit identischem Text, wie hier. Dedupliziere nach lang und behalte das erste Vorkommen. Der Text wird von Mitwirkenden eingegeben und unverändert zurückgegeben; der ar-Eintrag enthält hier Etikettenfragmente, die keine Zutaten sind — validiere also, bevor du ihn in Strukturen parst.

Kategorie, Tags, Allergene und lang

category ist ein einziger kommagetrennter String von breit bis eng: Beverages and beverages preparations,Beverages,Carbonated drinks,Sodas,Colas,pt:bebidas cafeína. Trenne am Komma; die letzte Ebene ist die spezifischste. categories_tags enthält dieselben Ebenen als maschinenlesbare Tags (en:beverages, en:carbonated-drinks, en:colas) und ist der stabile Wert zum Filtern oder Gruppieren, weil sich der Anzeige-String ändert, wenn Mitwirkende das Produkt bearbeiten.

allergens und traces nutzen dieselben Tags im Stil en:milk, ebenso countries (en:albania, en:austria, en:belgium) und labels. null heißt, die Quelle hat nichts angegeben, nicht dass das Produkt allergenfrei ist; dieser Datensatz hat allergens: null und traces: null, ein Allergiehinweis sollte also „unbekannt“ lauten, nicht „keine“.

Mit ?lang=bg ergänzt die API category_localized als einen übersetzten String, category_segments_localized mit einem Eintrag pro Hierarchieebene und allergens_localized parallel zu allergens. Eine Ebene oder ein Tag ohne Wörterbucheintrag ist im Array null; halte den Index also parallel zu categories_tags oder allergens und falle bei null-Plätzen auf das englische Tag zurück.

Bewertungen, Portionsgröße und zusammengefasste Nährwerte

nutriscore ist ein Kleinbuchstabe (hier e), nova_group eine Zahl (4) und ecoscore_grade ein String, der ein Buchstabe oder ein Sentinel wie not-applicable sein kann, was dieses Getränk zurückgibt. Behandle alle drei als nullable und ordne not-applicable keinem Farbband zu.

serving_size_raw und quantity sind Freitext, vom Etikett kopiert. serving_size_raw lautet 1 can (330 ml) und eignet sich für die Anzeige; quantity lautet bei diesem Datensatz 0kg, ein Fehler der Mitwirkenden — berechne das Packungsgewicht daraus also nie ohne Plausibilitätsprüfung.

nutrition_summary liefert sechs Werte pro 100 g: energy_kcal, proteins_g, carbs_g, fat_g, sugars_g und fiber_g. Jeder kann einzeln null sein, und das Objekt kann null sein, wenn die Quelle keine Nährwerttabelle hat. Es deckt eine Listenzeile oder einen schnellen Vergleich ab; die vollständigen 40+ Nährstoffe liegen bei der Nährwert-API unter /v1/foods/{id}/nutrients mit derselben id.

Stabile IDs, Caching und der übliche Ablauf

Die id ist deterministisch und aus der Quelle und der eigenen Produkt-ID der Quelle abgeleitet, sodass dasselbe Produkt bei jedem Reimport dieselbe UUID bekommt. Speichere IDs in deinen eigenen Tabellen und hole sie Monate später erneut, ohne Zuordnungsschritt. barcode ist im Schema nullable, bevorzuge also die id statt des Barcodes als Join-Schlüssel.

Ein 200 trägt Cache-Control: public, max-age=300 und ein 404 max-age=60, sodass ein CDN oder HTTP-Cache vor deinem Dienst sie ohne Konfiguration beachtet. Cachest du in deiner eigenen Datenbank, nimm id plus lang als Schlüssel, da sich die lokalisierten Schlüssel je Sprache unterscheiden.

Der übliche Ablauf: Hole eine id aus der Lebensmittel-Suche-API oder der Barcode-Abfrage-API, speichere sie und rufe diesen Endpunkt auf, wenn eine Detailansicht den vollständigen Datensatz braucht. Um viele gespeicherte IDs auf einmal zu aktualisieren, nimmt die Bulk-Lebensmittelabfrage-API ab Starter eine Liste in einer Anfrage. Bilder sind Fotos von Open-Food-Facts-Mitwirkenden auf images.openfoodfacts.org, und Datensätze aus anderen Quellen haben womöglich keines — zeige also immer einen Platzhalter, wenn image_url null ist.

Was du damit baust

Produktdetailseiten

Rendere eine reichhaltige Lebensmittelseite aus einem kanonischen Datensatz.

Datenanreicherungs-Pipelines

Reichere deinen Katalog mit Zutaten, Allergenen und Bewertungen an.

Forschung & Analytik

Arbeite mit einer sauberen, normalisierten Sicht auf zwei öffentliche Datensätze.

Limits pro Tarif

Free 100 Anfragen/Tag, 1/s dauerhaft, Burst 5
Starter 5.000 Anfragen/Tag, 5/s dauerhaft, Burst 25
Pro 25.000 Anfragen/Tag, 20/s dauerhaft, Burst 100
Enterprise 100.000 Anfragen/Tag, 50/s dauerhaft, Burst 250

Jede Antwort enthält Header X-RateLimit-* mit dem verbleibenden Budget; jede 429 enthält Retry-After . Tarife vergleichen →

Fehler und wie du sie behandelst

401 — Der X-API-Key-Header fehlt oder der Schlüssel ist nicht gültig.

Sende einen aktiven Schlüssel aus deinem Dashboard; der Body ist {error, message} wie bei jedem anderen Fehler.

404 — Die id ist eine wohlgeformte UUID, aber kein Produkt hat sie.

Entferne die id aus deinem Speicher; das 404 ist 60 Sekunden cachebar, wiederhole es also nicht in einer Schleife.

422 — Die id im Pfad ist keine UUID (zum Beispiel ein Barcode oder ein Slug).

Löse Barcodes über die Barcode-Abfrage-API auf und übergib hier nur UUIDs.

429 — Der Schlüssel hat seinen Sekunden-Burst überschritten oder das Konto sein Tageskontingent aufgebraucht.

Warte die in Retry-After genannten Sekunden und mach dann weiter; beobachte X-RateLimit-Second-Remaining und X-RateLimit-Daily-Remaining, um früher zu drosseln.

Im Vergleich zu anderen APIs

Die meisten Lebensmitteldaten-APIs liefern entweder einen rohen Open-Food-Facts-Dump oder einen reinen USDA-Datensatz, jeweils in eigener Form. FoodBase liefert beide Quellen über ein Schema, sodass ein openfoodfacts-Produkt und ein USDA-Produkt dieselben Schlüssel und Nullbarkeitsregeln teilen und du einen einzigen Parser schreibst. IDs sind deterministisch statt Zeilennummern und überleben daher Reimporte, und der Datensatz enthält bereits Kategorie-Tags, Allergen-Tags und sechs zusammengefasste Nährstoffe. Der Kompromiss: Das ist eine normalisierte Sicht, nicht der Upstream-Editor — Fehler von Mitwirkenden wie eine quantity von 0kg kommen so an, wie sie sind, und die vollständige Nährwerttabelle liegt bei der Nährwert-API statt in dieser Antwort.

Zum vollständigen Vergleich der Lebensmitteldaten-APIs →

Häufige Fragen

Woher bekomme ich eine id für diesen Endpunkt? +

Jedes Ergebnis der Lebensmittel-Suche-API und jeder Datensatz der Barcode-Abfrage-API enthält die id. Sie wird aus der Quelle und deren Produktkennung abgeleitet — speichere sie einmal und verwende sie über Importe hinweg wieder.

Warum ist name ein Array, und was ist lang main? +

Produkte tragen Namen in mehreren Sprachen, daher listet name {lang, text}-Paare. Der Eintrag mit lang main spiegelt name_default und ist der Haupttext der Quelle; wähle den Eintrag passend zu deiner UI-Sprache und falle auf name_default zurück.

Was ändert ?lang=? +

Es ergänzt category_localized, category_segments_localized und allergens_localized für en, fr, es, de, it oder bg. Sonst ändert sich nichts im Datensatz, und jedes Tag ohne Übersetzung ist in diesen Feldern null.

Heißt allergens: null, dass das Produkt keine Allergene hat? +

Nein. null heißt, die Quelle hat gar keine Allergendaten erfasst, zeige also einen Unbekannt-Zustand statt eines Sicher-Labels. Nur ein nicht leeres Array ist eine positive Information, und auch das spiegelt nur wider, was Mitwirkende von der Verpackung abgetippt haben.

Sind die Nährwerte in dieser Antwort die vollständige Tabelle? +

Nein. nutrition_summary enthält energy_kcal, proteins_g, carbs_g, fat_g, sugars_g und fiber_g pro 100 g; den vollständigen Satz von 40+ Nährstoffen liefert die Nährwert-API unter /v1/foods/{id}/nutrients mit derselben id.

Kann ich den Datensatz auf meiner Seite cachen? +

Ja. Ein 200 ist mit Cache-Control: public, max-age=300 markiert und ein 404 mit max-age=60, sodass jeder HTTP-Cache oder CDN sie halten kann; für längere Speicherung nimm id und lang als Schlüssel und aktualisiere nach deinem eigenen Zeitplan.

Hat dieser Endpunkt ein eigenes Kontingent? +

Nein. Er zieht vom normalen Anfragekontingent des Tarifs, das alle Schlüssel des Kontos teilen, während das Sekundenlimit pro Schlüssel gilt. Nur die Nährwert-API hat im Free-Tarif ein separates Tageskontingent.

Leg jetzt los mit der Lebensmittel-Datenbank API

Kostenlos starten. Keine Kreditkarte nötig.

API-Schlüssel holen Zum Dashboard