adidas APIadidas.de ↗
Access adidas.de product data via API: search products, browse categories, get pricing, images, ratings, and real-time size availability for the German Adidas store.
What is the adidas API?
The adidas.de API exposes 4 endpoints covering product search, category browsing, detailed product data, and real-time stock availability from the German Adidas store. The get_product_details endpoint returns over 10 fields per product including EUR pricing, image arrays, average ratings, sport classification, surface types, and sustainability metadata. Use search_products or browse_category to retrieve paginated product lists and feed IDs directly into the detail and availability endpoints.
curl -X GET 'https://api.parse.bot/scraper/858f06a5-fc5f-4fba-9f8f-7d57338bc118/search_products?sz=2&query=shoes&start=0' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace adidas-de-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""
Adidas Germany API - Parse Bot Scraper Client
Get your API key from: https://parse.bot/settings
"""
import os
import requests
from typing import Optional, Dict, Any, List
class ParseClient:
"""Client for interacting with the Adidas Germany Parse API."""
def __init__(self, api_key: Optional[str] = None):
"""
Initialize the Parse API client.
Args:
api_key: API key for authentication. If not provided, reads from PARSE_API_KEY env var.
"""
self.base_url = "https://api.parse.bot"
self.scraper_id = "858f06a5-fc5f-4fba-9f8f-7d57338bc118"
self.api_key = api_key or os.getenv("PARSE_API_KEY")
if not self.api_key:
raise ValueError("API key must be provided or set in PARSE_API_KEY environment variable")
def _call(self, endpoint: str, method: str = "POST", **params) -> Dict[str, Any]:
"""
Make a request to the Parse API.
Args:
endpoint: The API endpoint name.
method: HTTP method (GET or POST).
**params: Query/body parameters for the request.
Returns:
JSON response from the API.
"""
url = f"{self.base_url}/scraper/{self.scraper_id}/{endpoint}"
headers = {
"X-API-Key": self.api_key,
"Content-Type": "application/json"
}
if method.upper() == "GET":
response = requests.get(url, headers=headers, params=params)
else: # POST
response = requests.post(url, headers=headers, json=params)
response.raise_for_status()
return response.json()
def search_products(
self,
query: Optional[str] = None,
gender: Optional[str] = None,
size: Optional[str] = None,
start: int = 0,
sz: int = 48
) -> Dict[str, Any]:
"""
Search for products using keywords and filters.
Args:
query: Search keyword (e.g., 'shoes', 'running').
gender: Gender filter ('manner', 'frauen', 'kinder', 'unisex').
size: Size filter (e.g., 'xs', 's', 'm', 'l', 'xl', '2xl', '42').
start: Starting index for pagination.
sz: Number of items per page.
Returns:
Dictionary containing products list and total count.
"""
params = {
"start": start,
"sz": sz
}
if query:
params["query"] = query
if gender:
params["gender"] = gender
if size:
params["size"] = size
return self._call("search_products", method="GET", **params)
def browse_category(
self,
category: str,
gender: Optional[str] = None,
size: Optional[str] = None,
start: int = 0,
sz: int = 48
) -> Dict[str, Any]:
"""
Browse products within a specific category.
Args:
category: Category to browse (e.g., 'shoes', 'clothing', 'accessories').
gender: Gender filter.
size: Size filter.
start: Starting index for pagination.
sz: Number of items per page.
Returns:
Dictionary containing products list and total count.
"""
params = {
"category": category,
"start": start,
"sz": sz
}
if gender:
params["gender"] = gender
if size:
params["size"] = size
return self._call("browse_category", method="GET", **params)
def get_product_details(self, product_id: str) -> Dict[str, Any]:
"""
Retrieve full product details including description, images, and attributes.
Args:
product_id: Product ID (e.g., 'IF6490').
Returns:
Dictionary containing product details.
"""
return self._call("get_product_details", method="GET", product_id=product_id)
def get_product_availability(self, product_id: str) -> Dict[str, Any]:
"""
Check real-time stock availability and sizes for a product.
Args:
product_id: Product ID (e.g., 'KC8639').
Returns:
Dictionary containing availability status and variation list.
"""
return self._call("get_product_availability", method="GET", product_id=product_id)
def get_men_tops_xxl(self, limit: Optional[int] = None) -> Dict[str, Any]:
"""
Extract all men's tops available in size XXL with prices.
Args:
limit: Maximum number of products to return. Omitting returns all available results.
Returns:
Dictionary containing products list, count, and total.
"""
params = {}
if limit:
params["limit"] = limit
return self._call("get_men_tops_xxl", method="GET", **params)
def format_price(price: Optional[float]) -> str:
"""Format price as currency."""
if price is None:
return "N/A"
return f"€{price:.2f}"
def main():
"""Demonstrate a practical workflow using the Parse API."""
# Initialize the client
client = ParseClient()
print("\n" + "=" * 100)
print("Adidas Germany API - Parse Bot Demo".center(100))
print("=" * 100)
# Workflow 1: Search for men's running shoes
print("\n[STEP 1] Searching for men's running shoes...")
print("-" * 100)
search_results = client.search_products(
query="running shoes",
gender="manner",
sz=4
)
products = search_results.get("data", {}).get("products", [])
total_found = search_results.get("data", {}).get("total", 0)
if not products:
print("No products found. Exiting.")
return
print(f"Found {total_found} products total. Processing first {len(products)}...\n")
product_details_list = []
# Workflow 2: For each product, get full details and availability
for idx, product in enumerate(products, 1):
product_id = product["id"]
sale_price = product.get("sale_price")
price = product["price"]
print(f" {idx}. {product['name']}")
print(f" ID: {product_id}")
print(f" Price: {format_price(price)}", end="")
if sale_price and sale_price < price:
discount = int((1 - sale_price / price) * 100)
print(f" → Sale: {format_price(sale_price)} (Save {discount}%)")
else:
print()
# Get detailed product information
try:
details_response = client.get_product_details(product_id)
details = details_response.get("data", {})
product["details"] = details
# Check availability
availability_response = client.get_product_availability(product_id)
availability = availability_response.get("data", {})
product["availability"] = availability
product_details_list.append(product)
status = availability.get("availability_status", "UNKNOWN")
variations = availability.get("variation_list", [])
in_stock_sizes = [
v.get("size") for v in variations
if v.get("availability_status") == "IN_STOCK"
]
backorder_sizes = [
v.get("size") for v in variations
if v.get("availability_status") == "BACKORDER"
]
print(f" Status: {status}")
if in_stock_sizes:
display_sizes = in_stock_sizes[:4]
print(f" In Stock: {', '.join(display_sizes)}", end="")
if len(in_stock_sizes) > 4:
print(f" ... and {len(in_stock_sizes) - 4} more")
else:
print()
if backorder_sizes:
print(f" Backorder: {', '.join(backorder_sizes[:2])}", end="")
if len(backorder_sizes) > 2:
print(f" ... and {len(backorder_sizes) - 2} more")
else:
print()
except Exception as e:
print(f" Error fetching details: {e}")
# Workflow 3: Find the cheapest product
print("\n" + "=" * 100)
print("[STEP 2] Finding best value...")
print("-" * 100)
if product_details_list:
cheapest = min(
product_details_list,
key=lambda x: x.get("sale_price") if x.get("sale_price") else x["price"]
)
print(f"\nBest Price Found:")
print(f" Name: {cheapest['name']}")
print(f" ID: {cheapest['id']}")
print(f" Regular Price: {format_price(cheapest['price'])}")
if cheapest.get("sale_price") and cheapest["sale_price"] < cheapest["price"]:
discount = int((1 - cheapest["sale_price"] / cheapest["price"]) * 100)
print(f" SALE Price: {format_price(cheapest['sale_price'])} (-{discount}%)")
# Get available sizes for best deal
availability_data = cheapest.get("availability", {})
variations = availability_data.get("variation_list", [])
available_sizes = [
v.get("size") for v in variations
if v.get("availability_status") == "IN_STOCK"
]
if available_sizes:
print(f" Available Sizes: {', '.join(available_sizes[:6])}")
# Workflow 4: Browse shoes category for specific size
print("\n" + "=" * 100)
print("[STEP 3] Browsing shoes category for size 42...")
print("-" * 100)
category_results = client.browse_category(
category="shoes",
size="42",
sz=5
)
category_products = category_results.get("data", {}).get("products", [])
category_total = category_results.get("data", {}).get("total", 0)
print(f"\nFound {category_total} shoes in size 42. Showing {len(category_products)}:\n")
for idx, product in enumerate(category_products, 1):
sale_price = product.get("sale_price")
price = product["price"]
price_display = format_price(price)
if sale_price and sale_price < price:
discount = int((1 - sale_price / price) * 100)
price_display = f"{format_price(sale_price)} (was {format_price(price)}, save {discount}%)"
print(f" {idx}. {product['name']}")
print(f" Price: {price_display}")
# Workflow 5: Get men's tops specifically in XXL
print("\n" + "=" * 100)
print("[STEP 4] Fetching men's tops available in XXL...")
print("-" * 100)
xxl_results = client.get_men_tops_xxl(limit=6)
xxl_products = xxl_results.get("data", {}).get("products", [])
xxl_count = xxl_results.get("data", {}).get("count", 0)
xxl_total = xxl_results.get("data", {}).get("total", 0)
print(f"\nTotal XXL tops available: {xxl_total} | Showing: {len(xxl_products)}\n")
sale_count = 0
for idx, product in enumerate(xxl_products, 1):
sale_price = product.get("sale_price")
price = product["price"]
if sale_price and sale_price < price:
discount_pct = int((1 - sale_price / price) * 100)
print(f" {idx}. {product['name']}")
print(f" {format_price(sale_price)} (was {format_price(price)}, save {discount_pct}%)")
sale_count += 1
else:
print(f" {idx}. {product['name']}")
print(f" {format_price(price)}")
# Summary
print("\n" + "=" * 100)
print("Summary".center(100))
print("-" * 100)
print(f"✓ Searched for products: {len(products)} items retrieved")
print(f"✓ Fetched details & availability: {len(product_details_list)} items")
print(f"✓ Browsed shoes category: {len(category_products)} items (of {category_total} total)")
print(f"✓ Retrieved XXL tops: {len(xxl_products)} items (of {xxl_total} total)")
if sale_count > 0:
print(f"✓ Sales found: {sale_count} items on sale!")
print("=" * 100)
print("Demo completed successfully!".center(100))
print("=" * 100 + "\n")
if __name__ == "__main__":
main()Search for products on adidas.de using keywords and optional filters for gender and size. Returns paginated results with product names, prices, and images.
| Param | Type | Description |
|---|---|---|
| sz | integer | Number of results per page |
| size | string | Filter by size, lowercase (e.g. 'xs', 's', 'm', 'l', 'xl', '2xl', '3xl', '42', '44') |
| query | string | Search keyword (e.g. 'shoes', 'running', 't-shirt') |
| start | integer | Pagination start index |
| gender | string | Filter by gender: 'manner', 'frauen', 'kinder', 'unisex' |
{
"type": "object",
"fields": {
"total": "integer total number of matching products",
"products": "array of product summaries with name, id, price, sale_price, url, img"
},
"sample": {
"data": {
"total": 3762,
"products": [
{
"id": "IF6490",
"img": "https://assets.adidas.com/images/w_383,h_383,f_auto,q_auto,fl_lossy,c_fill,g_auto/08c7c0fc4ae84932864226ad74075e6e_9366/Handball_Spezial_Schuh_Braun_IF6490_00_plp_standard.jpg",
"url": "https://www.adidas.de/handball-spezial-schuh/IF6490.html",
"name": "Handball Spezial Schuh",
"price": 110,
"sale_price": null
}
]
},
"status": "success"
}
}About the adidas API
Search and Browse
The search_products endpoint accepts a query string (e.g. 'running', 'shoes') and returns a total count plus an array of product summaries, each containing name, id, price, sale_price, url, and img. Pagination is controlled via start (offset index) and sz (results per page). Results can be filtered by gender using German-language values: 'manner' (men), 'frauen' (women), 'kinder' (kids), or 'unisex'. The browse_category endpoint works identically but scopes results to a category keyword like 'shoes', 'clothing', or 'accessories'.
Product Details
get_product_details takes a product_id from search or browse results and returns a richer payload: full images array, rating, sport classification, unisex flag, weight in grams, and surface array indicating compatible terrain or activity surfaces. The url field links directly to the product page on adidas.de, and pricing is expressed in EUR.
Stock Availability
get_product_availability accepts a product_id and returns variation_list — an array of size/color variants — along with an availability_status string indicating current stock state. This endpoint reflects real-time inventory, making it useful for monitoring size restocks or sold-out statuses on specific SKUs.
Coverage Scope
All data is scoped to adidas.de, the German regional Adidas storefront. Prices are in EUR. Gender filter values follow German naming conventions ('manner', 'frauen', 'kinder'), which differ from other regional Adidas sites. Category values are English keywords that map to adidas.de's main navigation sections.
The adidas API is a managed, monitored endpoint for adidas.de — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when adidas.de changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official adidas.de API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Monitor EUR price drops and sale prices for specific Adidas product IDs using
get_product_details. - Build a size-restock alert system by polling
get_product_availabilityfor target product IDs and checkingvariation_listchanges. - Aggregate product catalogs by category using
browse_categorywith pagination to collect all shoes or clothing listings. - Filter search results by gender and size to power a localized German-market product discovery tool.
- Extract
ratingandsportclassification fields to compare product lines across Adidas running, football, or training categories. - Track
sale_pricevspricefields from search results to identify discounted inventory across the German storefront. - Cross-reference
surfaceandweightfields from product details to build a sport-specific gear recommendation dataset.
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does Adidas offer an official developer API for adidas.de product data?+
What does `get_product_availability` return beyond a simple in-stock flag?+
get_product_availability returns a variation_list array, which contains individual size and color variants for the product, and an availability_status string reflecting the overall stock state. This lets you check not just whether a product is available, but which specific size or color variants are in stock at a given moment.Are product reviews or individual user review text included in the API responses?+
rating number from get_product_details but does not expose individual review text, reviewer names, or review counts. You can fork the API on Parse and revise it to add an endpoint targeting per-product review data.Does the API cover regional Adidas sites outside Germany, such as adidas.com or adidas.co.uk?+
How does pagination work across `search_products` and `browse_category`?+
start sets the zero-based offset into the result set and sz sets how many items to return per page. The response includes a total field with the full match count, so you can calculate how many pages exist and iterate through them by incrementing start by sz on each request.