adidas APIadidas.de ↗
Access adidas.de product data via API. Search products, browse categories, get full details, and check real-time stock availability for the German Adidas store.
What is the adidas API?
The adidas.de API provides 4 endpoints covering product search, category browsing, detailed product data, and real-time stock availability from the German Adidas storefront. The get_product_details endpoint returns pricing, size variations with GTINs, product attributes, and a full image/video asset list — all keyed off a product ID returned by search_products or browse_category.
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', 't-shirt') and optional filters for gender (German locale values: manner, frauen, kinder, unisex) and size (clothing sizes like 'm' or shoe sizes like '42'). Results are paginated via start and sz parameters and return an array of product summaries, each with name, id, price, sale_price, url, and img. The browse_category endpoint works identically but navigates by category slug (shoes, clothing, accessories) instead of a keyword query.
Product Details
get_product_details takes a product_id (e.g. IF6490) and returns a detailed record. The attribute_list object covers fields like color, sport type, material, and gender. The variation_list maps out every available size with its individual sku and gtin. The view_list includes all product images and videos with URLs and associated metadata. Pricing is broken down in pricing_information as currentPrice, standard_price, and standard_price_no_vat, making VAT-exclusive figures directly accessible. The product_description object contains the title, body text, subtitle, and a list of USPs.
Availability
get_product_availability accepts a product_id and returns the availability_status string plus a variation_list indicating which size SKUs are currently in stock. This reflects the live stock state of the German adidas.de store, not a cached snapshot, making it suitable for alerting or in-stock filtering workflows.
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 sale prices and compare
sale_priceagainststandard_priceacross a product category. - Build a size-availability alert by polling
get_product_availabilityfor specific product IDs. - Aggregate adidas.de product catalog data by category using
browse_categorywith pagination. - Extract GTINs from
variation_listinget_product_detailsfor barcode or inventory matching. - Filter German adidas products by gender and size for a localized product recommendation feed.
- Collect product image assets via
view_listfor use in editorial or comparison tools. - Track VAT-exclusive pricing via
standard_price_no_vatfor B2B or cross-border price analysis.
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 200 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
| Team | $300/mo | 20,000 | 300 req/min |
| Company | $1,000/mo | 100,000 | 500 req/min |
Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does adidas have an official developer API?+
What does `get_product_details` return that search results don't?+
name, id, price, sale_price, url, and img. get_product_details adds attribute_list (color, material, sport, gender), variation_list with per-size sku and gtin, the full view_list of image and video assets, pricing_information including the VAT-exclusive price, and the structured product_description with body text and USPs.Are product reviews or ratings returned by any endpoint?+
Does the API cover adidas stores other than adidas.de?+
manner, frauen, etc.). Other regional storefronts are not covered. You can fork it on Parse and revise it to target a different country's adidas domain.What is the `start` parameter in search and browse, and are there limits on page size?+
start parameter is a zero-based offset into the result set, and sz controls how many results are returned per call. The total field in each response tells you the full count of matching products so you can calculate how many pages to fetch.