Tony Wang5 Min. LesezeitUlta Beauty scrapen in 2026 (API & Python)
Durchsuche Ulta Beautys Katalog und hol volle Produktdetails — Preis, Bewertung, Reviews und jede Farb-/Shade-Variante — als JSON.
Am schnellsten scrapst du Ulta Beauty 2026, indem du eine strukturierte API aufrufst, die normalisiertes JSON für die Stichwortsuche und volle Produktdetails liefert — Preis, Bewertung, Reviews, Bilder und jede Farb-/Shade-Variante — statt Ulta.coms Seiten selbst zu parsen. Ulta.com ist ohne Konto durchsuchbar, aber die Terms and Conditions benennen Scraping und automatisierte Datensammlung ausdrücklich als ohne Erlaubnis verboten. Dieser Guide behandelt alle drei Ansätze, was jeder liefert, wo DIY scheitert, und die rechtlichen Grundlagen.
Warum Ulta Beauty scrapen?
Ulta Beautys Produktkatalog treibt an:
- Preis-Intelligenz — verfolgen, wie sich der Preis eines Produkts über die Zeit hinweg über Marken und Kategorien hinweg bewegt.
- Sortimentsrecherche — sehen, welche Marken und Shades eine Kategorie führt und wie sich die Abdeckung verschiebt.
- Review- und Sentiment-Analyse — Rating- und Review-Count-Trends für eine Produktlinie abrufen.
- Shade- und Variantenabdeckung — jede Farbe/jeden Shade, in dem ein Produkt erhältlich ist, kartieren — nützlich für Katalog- und Bestandsrecherche in der Beauty-Branche.
- Wettbewerbs-Benchmarking — Preise und Bewertungen gegen andere Beauty-Händler vergleichen.
Ist es legal, Ulta Beauty zu scrapen?
Option 1: DIY in Python (und warum das scheitert)
Ulta Beautys Produktseiten rendern aus eingebetteten Seitendaten statt aus einem stabilen öffentlichen JSON-Endpoint, daher muss ein DIY-Scraper die gerenderte Seite abrufen und parsen:
import requests
from bs4 import BeautifulSoup
resp = requests.get(
"https://www.ulta.com/p/product-name-pimprod2020260",
headers={"User-Agent": "Mozilla/5.0 (compatible; research-bot/1.0)"},
)
soup = BeautifulSoup(resp.text, "html.parser")
# Price, rating, and color/shade variants are embedded in page data,
# not consistently exposed as selectable markup
Es funktioniert in der Demo und geht dann kaputt:
- Die Terms and Conditions sind eindeutig. Ulta Beauty nennt „scraping technology or fully automated systems" direkt beim Namen und verbietet separat Software, die ohne Erlaubnis Informationen der Services sammelt — das ist kein Grenzfall.
- Aktive Bot-Abwehr am Edge. Naive, unauthentifizierte Requests werden angefochten oder blockiert, und ein browserbasierter Scraper braucht laufende Pflege, sobald sich die Abwehr aktualisiert.
- Jedes Produkt trägt einen Variantenbaum, nicht einen einzelnen Preis. Ein einzelnes Ulta-Beauty-Produkt ist typischerweise in mehreren Farben oder Shades erhältlich, jede mit eigener SKU — ein reiner Page-Fetch liefert dir nur die Variante, die standardmäßig rendert, nicht das volle Set.
- Keine Self-Service-öffentliche API. Ulta Beauty hat kein offizielles Developer-Programm — es gibt keinen sanktionierten Kanal, über den ein externer Entwickler programmatischen Zugriff beantragen kann.
Option 2: No-Code-Tools
Marketplace-Scraper-Actors für Ulta Beauty existieren und eignen sich für einen einmaligen Abzug einer Kategorie oder einer kurzen Produktliste, aber sie erben dieselbe Bot-Abwehr-Fragilität wie DIY und liefern dir kein stabiles, versioniertes Schema — oder verlässliche Variantenabdeckung — auf dem du eine Pipeline aufbauen kannst.
Option 3: Eine strukturierte Ulta-Beauty-API
Für einen wiederholbaren Workflow liefert Crawloras Ulta-Beauty-API normalisiertes JSON für Suche und Produktdetails — kein Page-Parsing oder Pflege der Bot-Abwehr, und anmeldefrei. Nach Stichwort suchen:
curl "https://api.crawlora.net/api/v1/ulta/search?query=mascara" \
-H "x-api-key: $CRAWLORA_API_KEY"
Dann eine Produkt-id auflösen und volle Details holen, inklusive jeder Farb-/Shade-Variante, in Python:
import requests
h = {"x-api-key": "YOUR_API_KEY"}
base = "https://api.crawlora.net/api/v1/ulta"
hits = requests.get(f"{base}/search", headers=h, params={"query": "mascara"}).json()["data"]["products"]
product_id = hits[0]["product_id"]
detail = requests.get(f"{base}/product/{product_id}", headers=h).json()["data"]
# Select a specific color/shade variant with an optional sku
variant = requests.get(
f"{base}/product/{product_id}",
headers=h,
params={"sku": detail["variants"][0]["sku"]},
).json()["data"]
Eine Search-Response ist normalisiertes JSON (prüfe die docs für das vollständige Schema):
{
"code": 200,
"msg": "OK",
"data": {
"query": "mascara",
"page": 1,
"products": [
{
"product_id": "pimprod2020260",
"title": "Lash Sensational Sky High Mascara",
"brand": "Maybelline",
"price": 12.99,
"rating": 4.4,
"review_count": 5231
}
]
}
}
Produktdetails verschachteln Preis, Bewertung und jede Farb-/Shade-Variante nach SKU:
{
"data": {
"product_id": "pimprod2020260",
"title": "Lash Sensational Sky High Mascara",
"brand": "Maybelline",
"price": 12.99,
"rating": 4.4,
"review_count": 5231,
"images": ["https://media.ulta.com/..."],
"variants": [
{ "sku": "2020261", "shade": "Very Black", "in_stock": true },
{ "sku": "2020262", "shade": "Blackest Black", "in_stock": true }
]
}
}
Ein unbekanntes Stichwort liefert ein echtes leeres Ergebnis, und eine Seite jenseits der verfügbaren Ergebnisse liefert ein normales leeres Ergebnis statt eines Fehlers — bau deine Paginierungslogik so, dass sie bei einem leeren products-Array stoppt, statt ein Fehlersignal zu erwarten. Eine unbekannte product_id liefert einen 404. Ein fehlender oder ungültiger sku löst trotzdem das Basisprodukt mit seiner eigenen Standardvariante auf, sodass ein Detail-Call nie nur deshalb fehlschlägt, weil die SKU nicht gefunden wurde. Speichere eine Zeile pro product_id (oder pro SKU, falls du Shade-Level-Bestand verfolgst) und lass es nach Zeitplan erneut laufen, um Preis- und Bewertungsänderungen zu verfolgen.
Was du sammeln kannst
Öffentliche Produktdaten: paginierte Suchergebnisse (Produkt-id, Titel, Marke, Preis, Bewertung, Review-Count); volle Produktdetails (Preis, Bewertung, Review-Count, Bilder und jede käufliche Farb-/Shade-Variante, jede mit eigener SKU). Nur öffentliche Produktseitendaten — keine Konto-, Bestell- oder Zahlungsinformationen.
Grenzen und typische Herausforderungen
- Aktive Bot-Abwehr auf der Vorderseite. Rechne mit Anfechtungen bei naiven oder hochvolumigen automatisierten Requests direkt an Ulta.com.
- Die Terms and Conditions sind eindeutig. Ulta Beauty verbietet Scraping-Technologie und vollautomatisierte Datenextraktion und untersagt separat Software, die Informationen der Services sammelt, ohne explizite Erlaubnis.
- Varianten-Fan-out. Die volle Farb-/Shade-Palette eines Produkts liegt hinter demselben Detail-Call, geschlüsselt nach einer optionalen SKU — entscheide vorab, ob du das Basisprodukt, einen bestimmten Shade oder den gesamten Variantenbaum brauchst.
- Kein landesweiter Bulk-Export. Es gibt keinen offiziellen Feed von Ulta Beautys vollständigem Katalog; bau Abdeckung, indem du Suchanfragen iterierst.
- Nur öffentliche Daten. Das ist, was eine Produktseite bereits öffentlich zeigt — kein Weg um einen Login herum oder an Kontodaten heran.
Wo das eingesetzt wird
- Preis-Intelligenz — Preis- und Bewertungsänderungen über Marken und Kategorien hinweg über die Zeit verfolgen.
- Shade- und Sortimentsrecherche — kartieren, wie viele Farb-/Shade-Varianten eine Produktlinie führt und welche auf Lager sind.
- Review-Analyse — Rating- und Review-Count-Trends pro Produkt verfolgen.
Sources
Leg los mit dem Sammeln
Probier es zuerst kostenlos aus: jage eine beliebige öffentliche URL durch den Free Web Scraper, oder prüfe mit dem Anti-Bot Checker, ob eine Seite Bots blockiert — ohne Anmeldung.
Teste die Search- und Product-Endpoints im Playground, sieh dir das Schema in den API docs an und wirf einen Blick aufs pricing. Für dasselbe Big-Box-General-Merchandise-Muster sieh dir how to scrape Target und how to scrape Costco an; für einen Spezialeinzelhandels-Katalog mit derselben Search-to-Detail-Struktur sieh dir how to scrape Nike an. Siehe auch how to choose a web scraping API und is web scraping legal.
Häufig gestellte Fragen
Liefert die Ulta-Beauty-Suche für ein ungewöhnliches Stichwort leere Ergebnisse?
Ja — /ulta/search liefert ein echtes leeres Ergebnis für ein unbekanntes oder unsinniges Stichwort, und ein normales leeres Ergebnis (kein Fehler), wenn du eine Seite jenseits der verfügbaren Ergebnisse anfragst.
Kann ich eine bestimmte Farb- oder Shade-Variante eines Ulta-Beauty-Produkts bekommen?
Ja — übergib eine optionale sku an /ulta/product/{productId}, um eine bestimmte Farb-/Shade-Variante auszuwählen. Eine fehlende oder ungültige sku löst trotzdem das Basisprodukt mit seiner eigenen Standardvariante auf. Eine unbekannte productId liefert 404.