Free-Tarif

Lebensmittel-Suche API

Volltextsuche über 6,1 Millionen Lebensmittelprodukte nach Name, Marke oder Kategorie — nach Relevanz sortiert, paginiert und schnell. Suche in jeder Sprache, in der das Etikett gedruckt wurde (auch kyrillisch), und übergib lang=en|fr|es|de|it|bg für lokalisierte Namen, Kategorien und Allergene. Eine GET-Anfrage liefert sauberes JSON, das deine App sofort darstellen kann.

200 OK
GET /v1/foods/search?q=banana
curl -H "X-API-Key: food_•••" \
  "https://foodbase.dev/v1/foods/search?q=banana&limit=20"

{
  "data": [
    {
      "id": "034becf0-9aa7-c748-41aa-b71dd4df2bae",
      "name_default": "Bananes",
      "name_localized": "Bananas",
      "brand": "Bio Village, Marque Repère",
      "barcode": "3564707141710",
      "category": "...,Fruits,Fruits tropicaux,Bananes",
      "nutriscore": "a"
    }
  ],
  "total": 1000,
  "limit": 20,
  "offset": 0
}

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

Was du zurückbekommst

id

Stabile Lebensmittel-ID — verwende sie mit den anderen Endpunkten.

name_default

Produktname in seiner Hauptsprache.

name_localized / category_localized

Übersetzungen in der angeforderten lang (en, fr, es, de, it, bg), sofern vorhanden — sonst der Originaltext.

brand

Marke / Hersteller, falls bekannt.

barcode

EAN-13- / UPC-Barcode, falls verfügbar.

category

Oberste Lebensmittelkategorie.

total / limit / offset

Paginierungs-Metadaten für die gesamte Ergebnismenge.

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/search?q=banana&limit=20" \
  -H "X-API-Key: YOUR_API_KEY"
            

So funktioniert's

Was eine Suchanfrage macht

Eine Suche ist ein einzelnes GET mit dem Text in q. Die Wörter werden gemeinsam gegen Produktname und Marke abgeglichen, sodass q=olympus milk auch Produkte findet, deren Name nie „Olympus“ nennt, und das letzte Wort wird als Präfix behandelt, sodass milk olym schon passt, während die Nutzerin noch tippt. Alle Wörter müssen passen; es gibt kein ODER. q muss 1 bis 200 Zeichen lang sein; ein fehlendes oder leeres q wird abgelehnt, bevor eine Suche läuft — fange das leere Suchfeld also auf deiner Seite ab.

Produkte, die genau so heißen, wie du getippt hast, kommen zuerst, sodass banana erst Bananen und dann Bananenjoghurts listet und greek yogurt zuerst die schlichten griechischen Joghurts. Danach sind die Ergebnisse nach Relevanz sortiert, und bei gleich guter Übereinstimmung steht das beliebtere Produkt vorn. Eine Markensuche wie pringles überspringt den Schritt mit dem exakten Namen und bleibt in der Reihenfolge nach Beliebtheit; ein zweites Wort (eine Marke, eine Geschmacksrichtung) ist der schnellste Weg, ein bestimmtes Produkt nach oben zu holen.

Kategorienamen sind ein Fallback und nicht Teil des Hauptabgleichs: Nur wenn die Suche über Name und Marke nichts findet, sucht die API nach Produkten, deren Kategorie die Wörter enthält — in welcher Sprache die Kategorie auch gespeichert ist. Deshalb liefert eine Anfrage wie Seeds & Related Snacks oder Fruits tropicaux eine nach Beliebtheit sortierte Liste statt eines leeren Arrays.

  • Die Reihenfolge ist weder alphabetisch noch nach id. Sortiere das data-Array nicht auf dem Client neu.
  • Ist die Eingabe eine reine GTIN aus Ziffern, schick sie stattdessen an die Barcode-Abfrage-API: Sie löst Varianten mit führenden Nullen auf (0000080042556 findet 80042556), was eine Textsuche nicht kann.

Eine Ergebniszeile lesen

Jedes Element in data ist ein FoodListItem, eine schlankere Form als der vollständige Datensatz: id, barcode, source, name_default, brand, category, image_url, nutriscore und nova_group, dazu name_localized (immer vorhanden) und category_localized, wenn eine nicht-englische lang übergeben wird. Nährwerte gibt es hier nicht; die Liste ist zum Rendern von Zeilen gebaut, nicht für Berechnungen.

Mehrere Felder sind nullable, und das Beispiel zeigt es. Das Roshen-Bonbon „Banana land“ (4f995c13-c0df-bfcc-b6ec-449d312def75) hat image_url null und nova_group null; auch brand und barcode können null sein. nutriscore-Werte außerhalb von a bis e, wie das „n“ und das „u“ im Beispiel, bedeuten, dass keine Note berechnet wurde — zeige sie als „nicht bewertet“ an statt als den rohen Buchstaben.

category ist der vollständige Open-Food-Facts-Kategoriepfad, kommagetrennt von allgemein bis speziell („...,Fruits tropicaux,Bananes“ für die Bananen von Bio Village). Zeige das letzte Segment als Label oder das erste für eine grobe Gruppierung, und entferne Sprachpräfixe wie pt: vor der Anzeige. image_url ist ein Foto von Mitwirkenden auf images.openfoodfacts.org, also liefere für den null-Fall einen Platzhalter aus.

Paginierung, total und stabile IDs

limit liegt zwischen 1 und 100 (Standard 20), offset zwischen 0 und 10000. total ist eine gedeckelte Zahl: Die API hört bei 1.000 Treffern auf zu zählen, sodass der total-Wert 1000 im Beispiel für q=banana mit limit=3 bedeutet: mindestens 1.000. Zeige ihn als „1.000+“ und berechne aus ihm keine Nummer der letzten Seite.

Blättere, indem du limit auf offset addierst, bis data weniger als limit Elemente liefert. Weil offset bei 10000 endet, braucht eine Anfrage mit mehr Treffern ein engeres q, keine tiefere Seite.

  • IDs bleiben über FoodBase-Reimporte hinweg stabil: Speichere die id aus einer Suchzeile und löse sie später mit der Lebensmittel-Datenbank-API auf, ohne erneut zu suchen.
  • Das Ranking wird pro Anfrage berechnet und die Beliebtheit kann sich ändern, daher ist ein offset kein dauerhafter Cursor. Speichere IDs, keine Seitenpositionen.

In einer anderen Sprache suchen

lang ist standardmäßig en. Jede Sprache durchsucht den Eintrag dieser Sprache im name-Array des Produkts, sofern ihn Freiwillige oder die KI-Übersetzung von FoodBase geliefert haben, und fällt für Produkte ohne solchen Eintrag auf name_default zurück, den Namen wie auf dem Etikett gedruckt; die Marke ist immer Teil des Abgleichs. So erreicht lang=bg jedes Produkt, bevorzugt aber bulgarische Namen, wo es sie gibt, und ein kyrillisches Etikett wird unter jeder lang gefunden.

Die übergebene lang prägt auch die Ausgabe. name_localized enthält den übersetzten Namen: Das Beispiel, angefragt mit lang=en, macht aus „Puré de plátano y fresa“ „Banana and Strawberry Puree“ und fällt auf name_default zurück, wenn es nichts zu übersetzen gibt, wie „Banana land“ zeigt. Zeige name_localized, wenn nicht null, sonst name_default. category_localized ist kein Pflichtfeld und fehlt im Beispiel — lies es also defensiv.

Autovervollständigung und die Übergabe an vollständige Datensätze

Die Suche ist der richtige Endpunkt für eine Type-ahead-Box. Entprelle (debounce) die Tastenanschläge, fordere limit=8 bis 10 an und brich die laufende Anfrage ab, wenn die Nutzerin weitertippt, damit eine langsame frühere Antwort keine neuere überschreibt. Jeder Tastenanschlag, der die API erreicht, ist eine Anfrage gegen dein Tageskontingent — Debouncing ist also genauso Kostenkontrolle wie UX-Detail.

Wählt der Nutzer eine Zeile, rufe die Lebensmittel-Datenbank-API mit der id für den vollständigen Datensatz auf, oder die Nährwert-API, wenn du nur die Nährwerttabelle pro 100 g brauchst. Eine Suche plus eine Detailanfrage ist günstiger, als für jeden Vorschlag den vollständigen Datensatz zu holen.

Die aufgezeichnete Suchantwort trägt keinen Cache-Control-Header, anders als Lebensmitteldatensätze, die 300 Sekunden lang cachebar sind. Cache Suchergebnisse selbst, mit dem Schlüssel aus exaktem q, lang, limit und offset; dieselben kurzen Präfixe kommen in einer Type-ahead-Box ständig wieder. X-RateLimit-Second-Remaining zeigt, wie viel Burst übrig ist, und bei einem 429 sagt der Retry-After-Header, wie viele Sekunden du warten sollst.

Was du damit baust

Lebensmittelauswahl & Autovervollständigung

Treibe die Suchbox in einem Kalorientracker oder einer Rezept-App an — Type-ahead-Ergebnisse aus 6,1 Mio. Produkten.

Katalog-Anreicherung

Ordne deine eigenen SKUs per Name oder Marke den kanonischen Lebensmitteldatensätzen zu.

Entdeckungs-Feeds

Stöbere nach Kategorie oder Stichwort und baue kuratierte Lebensmittellisten.

Limits pro Tarif

Free 100 Anfragen/Tag, geteilt über die Schlüssel des Kontos; 1 Anfrage/s pro Schlüssel, Burst 5. Das Limit von 25 Nährwert-Aufschlüsselungen pro Tag gilt nicht für die Suche.
Starter 5.000 Anfragen/Tag; 5 Anfragen/s pro Schlüssel, Burst 25.
Pro 25.000 Anfragen/Tag; 20 Anfragen/s pro Schlüssel, Burst 100.
Enterprise 100.000 Anfragen/Tag; 50 Anfragen/s pro Schlüssel, 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, ist fehlerhaft oder gehört zu einem widerrufenen Schlüssel.

Prüfe den Header-Namen und den Schlüssel in deinem Dashboard. Wiederhole die Anfrage erst, wenn das behoben ist.

422 — q fehlt oder ist leer oder länger als 200 Zeichen, limit liegt außerhalb von 1 bis 100, offset außerhalb von 0 bis 10000, oder lang ist keiner der Werte en, fr, es, de, it, bg.

Lies das details-Array im Validation-Error-Body, um zu sehen, welcher Parameter fehlgeschlagen ist, und korrigiere die Anfrage auf dem Client. Wiederhole eine 422 nie unverändert.

429 — Der Sekunden-Burst für den Schlüssel ist aufgebraucht oder das Tageskontingent des Kontos ist verbraucht.

Warte die Anzahl Sekunden aus Retry-After ab und versuche es einmal erneut. Verwirf bei Autovervollständigung den veralteten Tastenanschlag, statt ihn einzureihen.

Im Vergleich zu anderen APIs

Eine allgemeine Suchmaschine oder ein E-Commerce-Katalog indiziert Text; die FoodBase-Suche indiziert Lebensmittelprodukte, sodass ein Treffer mit Barcode, Kategoriepfad, Nutri-Score und NOVA-Gruppe zurückkommt und mit einer id, die sich mit einer weiteren Anfrage zu einer Nährwerttabelle auflösen lässt. Der Kompromiss ist der Umfang: Sie gleicht Produktnamen und Marken ab, Kategorienamen nur als Fallback, nicht jedes Feld des Datensatzes, und eine nicht-englische lang durchsucht lokalisierte Namen, wo es sie gibt, und sonst Etikettennamen, statt deine Anfrage zu übersetzen. Es gibt keine Client-Bibliothek zu installieren und keinen Index, den du aufbauen musst — nur ein GET und ein JSON-Objekt. Wenn du Lebensmitteldaten-Anbieter nebeneinander abwägst, zeigt /compare/food-database-apis, was jeder abdeckt.

Zum vollständigen Vergleich der Lebensmitteldaten-APIs →

Häufige Fragen

Warum kommt total genau als 1000 zurück? +

Die Zählung ist gedeckelt. Bei 1.000 Treffern hört das Zählen auf, 1000 heißt also mindestens so viele. Zeige es als „1.000+“ und blättere per offset, bis data weniger als limit Zeilen liefert, statt total durch limit zu teilen.

Was liefert die API, wenn nichts passt? +

Ein 200 mit leerem data-Array, kein 404. Behandle das leere Array als deinen Kein-Ergebnis-Zustand. Weil jedes Wort in q passen muss, ist das Weglassen des unspezifischsten oder fehleranfälligsten Worts der übliche Ausweg, bevor du es anzeigst.

Kann ich nur nach Marke oder Kategorie suchen? +

Marke ja: Die Marke gehört zu dem, wogegen jedes Wort in q abgeglichen wird, also listet q=Hacendado die Produkte dieser Marke, und ein Produktwort grenzt die Liste ein. Kategorienamen werden nur versucht, wenn die Suche über Name und Marke nichts liefert, sodass q=Fruits tropicaux die unter dieser Kategorie eingeordneten Produkte zurückgibt, nach Beliebtheit statt nach Relevanz sortiert.

Enthält ein Suchergebnis Nährwerte? +

Nein. Suchzeilen haben die schlankere FoodListItem-Form ohne Nährwertfelder. Übergib die id der Zeile erst bei der Auswahl an die Nährwert-API statt für jeden Vorschlag, weil der Free-Tarif 25 Nährwert-Aufschlüsselungen pro Tag erlaubt.

Welche lang sollte eine bulgarische App übergeben? +

lang=bg durchsucht bulgarische lokalisierte Namen und liefert name_localized auf Bulgarisch, wo eine Übersetzung existiert. Etiketten, die kyrillisch als Standardname erfasst sind, werden mit lang=en gefunden, weil en den Standardnamen unabhängig von der Schrift durchsucht. Frage zuerst bg ab und falle bei leerem Ergebnis auf en zurück.

Ist das Ranking dasselbe wie auf der FoodBase-Website? +

Ja. Der Produkt-Explorer unter /products und die Kategorieseiten unter /categories/ laufen über denselben Endpunkt, du kannst also dort eine Anfrage testen und in deiner App dieselbe Reihenfolge für dasselbe q und dieselbe lang erwarten. Die Suche verbraucht keine KI-Credits; jeder Aufruf ist eine Anfrage gegen das Tageskontingent.

Leg jetzt los mit der Lebensmittel-Suche API

Kostenlos starten. Keine Kreditkarte nötig.

API-Schlüssel holen Zum Dashboard