Octopart Electronic Product Search

Site octopart.comTask electronic-product-details-8vawd0Version v1Updated Jul 13, 2026Category electronics-sourcing

Search Octopart's electronic-component catalog by keyword, MPN, or tech spec and return clean JSON: part identity, specs, distributor stock, and per-quantity pricing across DigiKey/Mouser/Arrow/Avnet/Farnell and 30+ other distributors. Recommended path is the Nexar GraphQL API (free with OAuth2 registration) — Octopart's public web UI is universally PerimeterX-walled on Browserbase. This skill was captured from a live agent session on octopart.com and publishes here verbatim, exactly as an agent receives it.

NoteSelectors and URL schemes drift as sites change. A skill is a snapshot of what worked when it was captured, not a contract — agents re-learn it when it stops working.

Purpose

Search Octopart's catalog of electronic components by keyword, part number, or technical spec, and return a clean JSON object containing each matching part's identity (MPN + manufacturer), specs, distributor availability, and current pricing tiers across distributors (DigiKey, Mouser, Arrow, Avnet, Farnell, etc.). Read-only — never adds to cart, never submits orders.

When to Use

  • Engineer/buyer needs to compare prices for an MPN (e.g. LM358, STM32F103C8T6, ERJ-2RKF1002X) across 30+ authorized distributors in one query.
  • Sourcing automation that decides which distributor to procure from based on current stock + price-break tiers.
  • Component cross-reference: given an MPN, find alternatives + their pricing.
  • BOM pricing rollups when you have a list of MPNs and need unit cost + stock at quantity break.
  • Any flow that would otherwise scrape octopart.com/search?q=... HTML — the Nexar GraphQL API is faster, structurally cleaner, and is the only path that reliably bypasses Octopart's PerimeterX (PX) bot wall.

Workflow

Octopart's public web UI (/search, /electronic-parts/..., /part/{mfr-slug}/{mpn}) is fronted by PerimeterX human-challenge — verified blocked across a plain browserless_agent session, a stealth + residential-proxy session, and fresh-session direct-to-detail navigation (4 iterations, all PX-walled). The supported path is the Nexar API. Altium operates Octopart's data as the public face of the Nexar GraphQL API at https://api.nexar.com/graphql — same dataset, no PX. The Nexar API is free for low volume after registering an application; OAuth2 client credentials are required.

1. One-time setup: register a Nexar API application

  1. Sign up at https://nexar.com/ (free).
  2. Go to https://portal.nexar.com/ → Applications → New Application.
  3. Pick the Supply scope (supply.domain) — this scope grants the Octopart product-search/pricing queries (supSearch, supSearchMpn, supParts).
  4. Copy clientId and clientSecret — store these in your agent's secret store, not in the SKILL.md or task input.

2. Acquire an OAuth2 access token

TOKEN=$(curl -sS -X POST https://identity.nexar.com/connect/token \
  -d "grant_type=client_credentials" \
  -d "client_id=${NEXAR_CLIENT_ID}" \
  -d "client_secret=${NEXAR_CLIENT_SECRET}" \
  -d "scope=supply.domain" \
  | node -e "let s='';process.stdin.on('data',c=>s+=c).on('end',()=>process.stdout.write(JSON.parse(s).access_token))")

Tokens are valid for ~24 hours. Cache and reuse — don't request a new one per query.

3. Run the search query

For a free-text search ("LM358", "10nf,25v,10%,X7R,0402", or "STM32" partial MPN), use supSearch:

query SearchProducts($q: String!, $limit: Int = 10) {
  supSearch(q: $q, limit: $limit, inStockOnly: false) {
    hits
    results {
      part {
        id
        mpn
        manufacturer {
          name
        }
        shortDescription
        category {
          name
          path
        }
        bestDatasheet {
          url
        }
        bestImage {
          url
        }
        medianPrice1000 {
          price
          currency
        }
        specs {
          attribute {
            shortname
            name
            group
          }
          displayValue
        }
        sellers {
          company {
            name
          }
          country
          offers {
            sku
            inventoryLevel
            moq
            packaging
            clickUrl
            prices {
              quantity
              price
              currency
            }
            updated
          }
        }
      }
    }
  }
}

For a guaranteed exact-MPN match (no fuzzy expansion), use supSearchMpn with the same selection set — it returns 1 hit per exact MPN.

POST to the GraphQL endpoint:

curl -sS -X POST https://api.nexar.com/graphql \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"query\": \"...above...\", \"variables\": {\"q\": \"LM358\", \"limit\": 5}}"

4. Reshape the response into the clean JSON contract

Map each results[].part into the output shape under ## Expected Output. Key rules:

  • Sort offers within a seller by prices[0].quantity ascending — the API doesn't guarantee order.
  • Pick the lowest-quantity-1 price across all sellers as the "best price" rollup field. If a seller's lowest tier is quantity > 1, fall back to their lowest tier.
  • Drop inventoryLevel: 0 offers unless include_out_of_stock: true was requested.
  • Normalize all prices to USD if needed — Nexar returns prices in the seller's listed currency. medianPrice1000 is pre-normalized in USD for the "best estimate" rollup.

Browser fallback

Not viable via a browser session. PerimeterX (/kdRQnL15/ proxying endpoints in robots.txt confirms the deployment) issues a "Press & Hold Human Challenge" iframe on every non-homepage request, including:

  • /search?q=... — blocked on a plain session, blocked on stealth + residential proxy
  • /electronic-parts/{category} — blocked
  • /part/{manufacturer-slug}/{mpn} — blocked even via direct navigation on a brand-new session

A raw HTTP fetch (e.g. a browserless_function that navigates to the origin then page.evaluates a same-origin fetch) does receive real HTML (no PX challenge), but part-detail pages are ~1.5-3 MB and the text return is ~200k-char capped, so project in-page. The JSON-LD <script type="application/ld+json"> block embedded in /part/{mfr}/{mpn} carries the Product schema.org graph with name, mpn, brand, offers[].price, offers[].priceCurrency, offers[].availability, offers[].seller — parse that (in-page) instead of the visual DOM. Note this yields only the headline qty=1 price; per-tier breaks remain API-only, so for pricing prefer the Nexar API.

Site-Specific Gotchas

  • PerimeterX is universally deployed on data pages. Verified 2026-05-19 across 4 iterations: /search?q=LM358 returned Block Type: PX, Reference: a0af2040-5340-... on a plain browserless_agent session, on a stealth + residential-proxy session (residential proxy IP 108.41.189.122, also blocked), and on a fresh stealth session navigating directly to /part/te-connectivity/66105-3. The homepage / is the only universally-reachable page on the first request of a session.
  • The PX flag is sticky to the session. Once any data page is challenged, subsequent loads (even of /) on the same session return PX too. There is no recovery within a session — release and create a new one, but the new one will still block at /search.
  • Don't waste iterations on selectors/CSS for /search. No selector strategy survives the challenge iframe. The skill exits at the PX wall, not at a render race.
  • A raw HTTP fetch bypasses PX (different fingerprint than headless Chrome), but Octopart part-detail pages are ~1.5-3 MB of JS-rendered HTML + inline JSON, so you must slice/project in-page (the text return is ~200k-char capped) rather than shipping the whole document. The sitemap index (product-sitemap-index.xml) and robots.txt are small and return cleanly — useful for enumerating MPN coverage but they contain no pricing data.
  • /part/{old-mpn-slug}-{numeric-id} 301-redirects to /part/{mfr-slug}/{mpn} — both URL forms resolve to the same detail page. The newer canonical form is /part/{mfr-slug}/{mpn}.
  • Nexar API rate limits: free tier is ~1,000 queries/month and ~20 QPS. For a single search-and-extract this is generous; for daily BOM pricing across hundreds of MPNs, request a paid tier or batch via supParts(ids: [...]).
  • Nexar OAuth2 endpoint is identity.nexar.com, not api.nexar.com. Common mistake — the GraphQL endpoint and the token endpoint live on different subdomains.
  • supSearch does fuzzy MPN expansion. Searching STM32 returns ~10k hits across the STM32 family — use supSearchMpn for exact MPN, or pass filters: { manufacturer_id: { eq: <id> } } to narrow.
  • medianPrice1000 is null for many parts — it's an aggregate that requires enough distributor signal. Fall back to the lowest sellers[].offers[].prices[] tier when computing a "current price" field.
  • sellers[].offers[].prices[] is per quantity break. A single seller may list 5–8 quantity breaks (1, 10, 100, 1000, 5000, 10000). Always pass through all tiers in the output, then surface a best_unit_price rollup at qty=1 for convenience.
  • inventoryLevel of null ≠ 0. null means the distributor didn't report stock to Octopart; 0 is reported zero. Treat them differently when filtering for available parts.
  • Octopart was acquired by Altium and rolled into the Nexar product family in 2018. Some older support docs (pre-2020) reference an octopart.com/api/v3/... REST API — that surface is now deprecated, robots.txt Disallows /api/v1/* through /api/v4/*, and the v3 keys no longer authenticate. The Nexar GraphQL endpoint is the only supported programmatic surface today.

Expected Output

{
  "query": "LM358",
  "method": "nexar-api",
  "hits": 1247,
  "results": [
    {
      "octopart_id": "518",
      "mpn": "LM358N",
      "manufacturer": "Texas Instruments",
      "short_description": "Dual operational amplifier, 8-Pin PDIP",
      "category": {
        "name": "Linear Amplifiers - Op Amps",
        "path": [
          "Electronic Parts",
          "Integrated Circuits (ICs)",
          "Linear ICs",
          "Linear Amplifiers - Op Amps"
        ]
      },
      "datasheet_url": "https://datasheet.octopart.com/LM358N-Texas-Instruments-datasheet-9646.pdf",
      "image_url": "https://sigma.octopart.com/.../LM358N.jpg",
      "specs": {
        "supply_voltage": "3 V to 32 V",
        "operating_temperature": "0 °C to 70 °C",
        "package": "PDIP-8",
        "channels": "2",
        "rohs": "Compliant"
      },
      "best_unit_price_usd": 0.42,
      "median_price_1000_usd": 0.18,
      "sellers": [
        {
          "name": "DigiKey",
          "country": "US",
          "offers": [
            {
              "sku": "296-1395-5-ND",
              "stock": 18432,
              "moq": 1,
              "packaging": "Tube",
              "click_url": "https://octopart.com/click/...",
              "prices": [
                { "qty": 1, "price": 0.49, "currency": "USD" },
                { "qty": 10, "price": 0.44, "currency": "USD" },
                { "qty": 100, "price": 0.31, "currency": "USD" },
                { "qty": 1000, "price": 0.21, "currency": "USD" }
              ],
              "updated": "2026-05-18T22:14:00Z"
            }
          ]
        },
        {
          "name": "Mouser",
          "country": "US",
          "offers": [
            {
              "sku": "595-LM358N",
              "stock": 9624,
              "moq": 1,
              "packaging": "Tube",
              "click_url": "https://octopart.com/click/...",
              "prices": [
                { "qty": 1, "price": 0.42, "currency": "USD" },
                { "qty": 10, "price": 0.39, "currency": "USD" },
                { "qty": 100, "price": 0.29, "currency": "USD" },
                { "qty": 1000, "price": 0.19, "currency": "USD" }
              ],
              "updated": "2026-05-18T23:01:00Z"
            }
          ]
        }
      ]
    }
  ]
}

If the browser-fallback path is ever unblocked (PX softens or the Fetch API cap is raised), the same shape is reconstructible from the <script type="application/ld+json"> Product block on /part/{mfr-slug}/{mpn}name → mpn, brand.name → manufacturer, description → short_description, offers[].price/.priceCurrency/.availability/.seller.name → sellers[].offers[].prices[0]. The browser path will NOT yield per-quantity break tiers (only the headline qty=1 price is in JSON-LD) — that's an API-only capability.

If the query yields zero hits:

{
  "query": "totally-fake-mpn-123",
  "method": "nexar-api",
  "hits": 0,
  "results": []
}

If the Nexar token request fails (bad credentials, scope mismatch):

{
  "query": "LM358",
  "method": "nexar-api",
  "error": "auth_failed",
  "detail": "invalid_client"
}

Call it

GET https://production-sfo.browserless.io/skills?token=TOKEN-HERE&domain=octopart.com&task=electronic-product-details-8vawd0