Octopart APIoctopart.com ↗
Search electronic components on Octopart. Get real-time pricing, stock levels, specs, datasheets, and seller offers across distributors via 4 API endpoints.
What is the Octopart API?
The Octopart API exposes 4 endpoints for querying electronic parts data, including distributor pricing, stock availability, technical specifications, and datasheets. The search_parts endpoint accepts keyword queries with filters for stock status, country, and currency, returning paginated results with seller offers. get_part_detail returns granular per-part data — specs, descriptions, images, and offer breakdowns — by Octopart part ID or manufacturer part number.
curl -X GET 'https://api.parse.bot/scraper/29bd1b9e-8808-4396-9ded-37aba5aa0ae4/search_parts?limit=3&query=capacitor&offset=0&country=US¤cy=USD' \ -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 octopart-com-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.
"""
Octopart API - Electronic Parts Search and Details
Search and retrieve detailed data for electronic parts from Octopart, including pricing,
stock, and specifications across multiple distributors.
Get your API key from: https://parse.bot/settings
"""
import os
import requests
from typing import Any, Optional
class ParseClient:
"""Client for interacting with the Parse Octopart API."""
def __init__(self, api_key: Optional[str] = None):
"""Initialize the Parse client with API credentials."""
self.base_url = "https://api.parse.bot"
self.scraper_id = "29bd1b9e-8808-4396-9ded-37aba5aa0ae4"
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 an API call to the Parse endpoint."""
url = f"{self.base_url}/scraper/{self.scraper_id}/{endpoint}"
headers = {
"X-API-Key": self.api_key,
"Content-Type": "application/json"
}
if method == "GET":
response = requests.get(url, headers=headers, params=params, timeout=30)
elif method == "POST":
response = requests.post(url, headers=headers, json=params, timeout=30)
else:
raise ValueError(f"Unsupported HTTP method: {method}")
response.raise_for_status()
return response.json()
def search_parts(
self,
query: str,
limit: int = 10,
offset: int = 0,
currency: str = "USD",
country: str = "US",
in_stock_only: bool = False
) -> dict[str, Any]:
"""
Search for electronic parts by keyword with pricing and availability.
Args:
query: Search keyword (e.g., 'resistor', 'capacitor', 'Arduino')
limit: Maximum number of results to return (default: 10)
offset: Number of results to skip (default: 0)
currency: Currency code for pricing (default: 'USD')
country: Country code for pricing and availability (default: 'US')
in_stock_only: Filter to only show in-stock parts (default: False)
Returns:
Dictionary containing search results and total hits
"""
return self._call(
"search_parts",
method="GET",
query=query,
limit=limit,
offset=offset,
currency=currency,
country=country,
in_stock_only=in_stock_only
)
def get_part_detail(
self,
part_id: Optional[str] = None,
mpn: Optional[str] = None,
manufacturer: Optional[str] = None,
currency: str = "USD",
country: str = "US"
) -> dict[str, Any]:
"""
Retrieve detailed information for a specific part by its ID or MPN.
Args:
part_id: Octopart part ID
mpn: Manufacturer Part Number
manufacturer: Manufacturer name (optional, used when searching by MPN)
currency: Currency code (default: 'USD')
country: Country code (default: 'US')
Returns:
Dictionary containing part details including specs and sellers
"""
params = {
"currency": currency,
"country": country
}
if part_id:
params["part_id"] = part_id
if mpn:
params["mpn"] = mpn
if manufacturer:
params["manufacturer"] = manufacturer
return self._call("get_part_detail", method="GET", **params)
def get_categories(self) -> dict[str, Any]:
"""
Retrieve the electronic parts category tree.
Returns:
Dictionary containing hierarchical categories
"""
return self._call("get_categories", method="GET")
def get_manufacturers(self) -> dict[str, Any]:
"""
Retrieve a list of electronic part manufacturers.
Returns:
Dictionary containing manufacturers with IDs and aliases
"""
return self._call("get_manufacturers", method="GET")
def format_price(price: float, currency: str = "USD") -> str:
"""Format price with currency symbol."""
symbols = {"USD": "$", "EUR": "€", "GBP": "£"}
symbol = symbols.get(currency, currency)
return f"{symbol}{price:.3f}"
def main():
"""Demonstrate a practical workflow with the Octopart API."""
# Initialize the client
client = ParseClient()
print("=" * 80)
print("OCTOPART API - ELECTRONIC PARTS SEARCH WORKFLOW")
print("=" * 80)
# Step 1: Search for capacitors with stock filter
print("\n[STEP 1] Searching for 'capacitor' (in stock only)...")
search_results = client.search_parts(
query="capacitor",
limit=5,
currency="USD",
country="US",
in_stock_only=True
)
total_hits = search_results.get("data", {}).get("total_hits", 0)
results = search_results.get("data", {}).get("results", [])
print(f"✓ Found {total_hits:,} matching parts")
print(f"✓ Displaying {len(results)} results\n")
part_ids = []
for i, part in enumerate(results, 1):
part_ids.append(part.get("id"))
print(f" [{i}] {part.get('name', 'Unknown')}")
print(f" MPN: {part.get('mpn', 'N/A')}")
print(f" Manufacturer: {part.get('manufacturer', 'N/A')}")
print(f" Description: {part.get('description', 'No description')[:70]}")
# Show quick pricing from sellers
sellers = part.get("sellers", [])
if sellers:
seller = sellers[0]
seller_name = seller.get("name", "Unknown")
offers = seller.get("offers", [])
if offers:
offer = offers[0]
inventory = offer.get("inventory_level", 0)
prices = offer.get("prices", [])
if prices:
price = prices[0].get("converted_price", 0)
currency = prices[0].get("converted_currency", "USD")
print(f" {seller_name}: {inventory} units @ {format_price(price, currency)}")
print()
# Step 2: Get detailed information for the first part
if part_ids:
print("[STEP 2] Fetching detailed specs for first part...")
first_part_id = part_ids[0]
detail = client.get_part_detail(part_id=first_part_id)
part_data = detail.get("data", {})
print(f"✓ Part ID: {part_data.get('id')}")
print(f" MPN: {part_data.get('mpn')}")
print(f" Manufacturer: {part_data.get('manufacturer', {}).get('name', 'N/A')}")
# Display specifications
specs = part_data.get("specs", [])
if specs:
print(f"\n Specifications:")
for spec in specs[:5]: # Show first 5 specs
attr = spec.get("attribute", {})
attr_name = attr.get("name", "Unknown")
value = spec.get("display_value", "N/A")
print(f" • {attr_name}: {value}")
# Display seller information with pricing tiers
print(f"\n Sellers & Pricing:")
sellers = part_data.get("sellers", [])
for seller in sellers[:3]: # Show top 3 sellers
company = seller.get("company", {})
seller_name = company.get("name", "Unknown")
is_auth = "✓" if seller.get("is_authorized") else "✗"
print(f"\n {seller_name} (Authorized: {is_auth})")
offers = seller.get("offers", [])
for offer in offers[:1]: # Show first offer per seller
inventory = offer.get("inventory_level", 0)
moq = offer.get("moq", 1)
sku = offer.get("sku", "N/A")
print(f" SKU: {sku}")
print(f" Stock: {inventory} units | MOQ: {moq}")
prices = offer.get("prices", [])
for price_tier in prices[:3]: # Show first 3 price tiers
price = price_tier.get("converted_price", 0)
quantity = price_tier.get("quantity", 0)
currency = price_tier.get("converted_currency", "USD")
print(f" Qty {quantity}: {format_price(price, currency)}/unit")
# Step 3: Search for resistors in different currency
print("\n" + "=" * 80)
print("[STEP 3] Searching for 'resistor' in EUR (European pricing)...")
resistor_search = client.search_parts(
query="resistor",
limit=3,
currency="EUR",
country="GB"
)
resistor_results = resistor_search.get("data", {}).get("results", [])
resistor_total = resistor_search.get("data", {}).get("total_hits", 0)
print(f"✓ Found {resistor_total:,} resistors")
print(f"✓ Displaying {len(resistor_results)} results with EUR pricing\n")
for i, resistor in enumerate(resistor_results, 1):
print(f" [{i}] {resistor.get('name', 'Unknown')}")
print(f" MPN: {resistor.get('mpn', 'N/A')}")
sellers = resistor.get("sellers", [])
if sellers:
for seller in sellers[:2]: # Show 2 sellers
seller_name = seller.get("name", "Unknown")
offers = seller.get("offers", [])
if offers:
offer = offers[0]
moq = offer.get("moq", 1)
inventory = offer.get("inventory_level", 0)
prices = offer.get("prices", [])
if prices:
price = prices[0].get("converted_price", 0)
currency = prices[0].get("converted_currency", "EUR")
print(f" {seller_name}: {format_price(price, currency)} (MOQ: {moq}, Stock: {inventory})")
print()
# Step 4: Search for a specific MPN and get its details
print("=" * 80)
print("[STEP 4] Searching for specific MPN 'RC0805FR-071K1L'...")
mpn_detail = client.get_part_detail(
mpn="RC0805FR-071K1L",
manufacturer="Yageo",
currency="USD",
country="US"
)
mpn_part = mpn_detail.get("data", {})
if mpn_part.get("id"):
print(f"✓ Found part by MPN")
print(f" Name: {mpn_part.get('mpn', 'N/A')}")
print(f" Manufacturer: {mpn_part.get('manufacturer', {}).get('name', 'N/A')}")
print(f" Slug: {mpn_part.get('slug', 'N/A')}")
descriptions = mpn_part.get("descriptions", [])
if descriptions:
print(f" Description: {descriptions[0].get('text', 'N/A')}")
# Show best available resources
best_image = mpn_part.get("best_image", {})
if best_image.get("url"):
print(f" Image: {best_image.get('url')}")
best_datasheet = mpn_part.get("best_datasheet", {})
if best_datasheet.get("url"):
print(f" Datasheet: {best_datasheet.get('url')}")
print("\n" + "=" * 80)
print("WORKFLOW COMPLETE")
print("=" * 80)
if __name__ == "__main__":
main()Search for electronic parts by keyword. Returns paginated results with pricing and availability from multiple distributors.
| Param | Type | Description |
|---|---|---|
| limit | integer | Maximum number of results to return. |
| queryrequired | string | Search keyword (e.g. 'resistor', 'capacitor', 'Arduino'). |
| offset | integer | Number of results to skip for pagination. |
| country | string | Country code for pricing and availability. |
| currency | string | Currency code for pricing. |
| in_stock_only | boolean | Filter to only show in-stock parts. |
{
"type": "object",
"fields": {
"results": "array of part objects with id, mpn, name, manufacturer, slug, description, image_url, datasheet_url, and sellers",
"total_hits": "integer total number of matching parts"
},
"sample": {
"data": {
"results": [
{
"id": "58145950",
"mpn": "224MKP275KB",
"name": "Cornell Dubilier 224MKP275KB",
"slug": "/part/cornell-dubilier/224MKP275KB",
"sellers": [
{
"name": "Master Electronics",
"offers": [
{
"moq": 500,
"sku": "224MKP275KB",
"prices": [
{
"price": 0.2522,
"currency": "USD",
"quantity": 1000,
"converted_price": 0.2522,
"converted_currency": "USD"
}
],
"inventory_level": 8002
}
],
"is_authorized": true
}
],
"image_url": "https://sigma.octopart.com/21540338/image/Cornell-Dubilier-224MKP275KB.jpg",
"description": "Film Capacitor, Polypropylene, 10% +Tol, 10% -Tol, 0.22uF, Through Hole Mount",
"manufacturer": "Cornell Dubilier",
"datasheet_url": "http://datasheet.octopart.com/224MKP275KB-Cornell-Dubilier-datasheet-158974572.pdf"
}
],
"total_hits": 3670923
},
"status": "success"
}
}About the Octopart API
Search and Filter Electronic Parts
The search_parts endpoint accepts a required query string (e.g. 'STM32F4', '0805 resistor') alongside optional parameters including limit, offset, country, currency, and in_stock_only. Each result object in the results array includes mpn, manufacturer, description, image_url, datasheet_url, and a sellers array. The total_hits field enables standard pagination logic. Filtering with in_stock_only: true narrows results to parts with at least one distributor showing availability.
Part Detail and Seller Offers
get_part_detail accepts either a part_id (Octopart's internal identifier) or an mpn, with an optional manufacturer parameter to disambiguate when multiple manufacturers share a part number. The response includes a specs array of attribute/display_value pairs covering electrical and mechanical characteristics, a sellers array with company, is_authorized, is_broker, and nested offers, plus best_datasheet and best_image objects containing direct URLs.
Categories and Manufacturers
get_categories returns the full category tree as a flat array of objects with id, name, path, and children. This is useful for building browse interfaces or mapping your own taxonomy to Octopart's hierarchy. get_manufacturers returns all manufacturers with at least 5 active parts, each with id, name, slug, and aliases — the aliases field is particularly useful for normalizing brand name variations (e.g. 'TI' vs 'Texas Instruments') in downstream data pipelines.
The Octopart API is a managed, monitored endpoint for octopart.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when octopart.com 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 octopart.com 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?+
- Build a BOM (bill of materials) tool that resolves MPNs to live distributor pricing and stock via
get_part_detail - Power a component search interface using
search_partswithin_stock_onlyfiltering for procurement workflows - Track cross-distributor price differences for a specific part by reading the
sellers[].offersarray - Normalize manufacturer names in a parts database using the
aliasesfield fromget_manufacturers - Generate category-browsable component catalogs using the parent-child hierarchy from
get_categories - Surface datasheet URLs automatically during hardware design review using the
best_datasheet.urlfield - Monitor availability for a watchlist of parts by polling
get_part_detailwith storedpart_idvalues
| 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 Octopart have an official developer API?+
What does the `sellers` field in `get_part_detail` include, and does it distinguish authorized distributors from brokers?+
sellers array includes a company name, a boolean is_authorized flag indicating whether the seller is a manufacturer-authorized distributor, and a boolean is_broker flag. Nested offers contain pricing and availability data per seller.Does `search_parts` return historical pricing or price trend data?+
sellers array in search results reflects current offer data only — there are no historical price fields in the response. The API covers current pricing, stock, and specs. You can fork it on Parse and revise to add a price-history tracking endpoint if you need that capability.Are parametric or spec-based searches supported (e.g. filter by capacitance or voltage rating)?+
query parameter; there is no spec-attribute filter in search_parts. The API covers keyword search, part detail, categories, and manufacturers. You can fork it on Parse and revise to add parametric filtering against the specs fields returned by get_part_detail.How does pagination work in `search_parts`?+
offset and limit parameters together with the total_hits integer in the response. For example, with limit=25 and total_hits=300, increment offset by 25 on each request to page through all results. There is no cursor-based pagination; offset-based paging is the only supported method.