skill
Electronics Industry Sites Skillpack
Public Made by Adomby adom
One skill per popular electronics-industry website (ST, TI, Mouser, DigiKey, SnapEDA, Ultra Librarian, Arrow, Analog, Microchip, Nordic, CSE, Octopart, JLCPCB, datasheets.com): which access lane works (fetch, curl, pup, nb, API), the bot defense each one runs, the exact failure signatures, and the task recipes. Verified live, dated, and built to grow.
← Commit history
correct the analog/Akamai mechanism: HTTP 403 at the edge before JS, not a sensor that failed to execute
1 file changed
+71−10
gen.py+71−10@@ -141,14 +141,14 @@ SITES = [ dict(slug="analog", name="Analog Devices (incl. Maxim, Linear)", domains=["www.analog.com"], what="Manufacturer. Product pages, datasheets, LTspice models, eval boards.",- defense="Akamai Bot Manager, strict. The single hardest case in this pack and the one that drove the 2026-09-14 investigation (see the root skill). TWO stacked causes, both measured: (1) browser VERSION - on CfT 148 the bmak sensor never initialised (typeof bmak undefined) and the edge denied; on CfT 152, matched to the installed Chrome, the sensor runs and the page loads; (2) egress IP - even on 152, loads from a VPN/Azure egress and denies from the bare office LAN NAT.",+ defense="Akamai Bot Manager, strict. The single hardest case in this pack and the one that drove the 2026-09-14 investigation (see the root skill). TWO stacked causes, both measured: (1) browser VERSION - on CfT 148 the edge answered HTTP 403 (AkamaiGHost) with a static Access Denied page; on CfT 152, matched to the installed Chrome, the same URL serves the real page. The 403 is decided at the HTTP layer before any page JavaScript runs, so this is a CONNECTION-fingerprint refusal, not a sensor failure (CfT 148 runs JS fine; typeof bmak undefined on a deny page is a symptom, the deny page has no sensor script); (2) egress IP - even on 152, loads from a VPN/Azure egress and denies from the bare office LAN NAT.", lanes={ "WebFetch": ("BLOCKED", "Akamai edge"), "curl": ("BLOCKED", "curl (92) HTTP/2 INTERNAL_ERROR in ~100 ms"), "pup": ("PARTIAL", "CfT 152 REQUIRED (on 148 always denied). On 152: LOADS from a clean egress (AdomLapper VPN, winvm Azure, bmak:object), DENIED from the bare office LAN (arav-rog, ConfRoomROG, bmak:undefined). 2026-09-14"), "nb": ("OK", "the user's real Chrome loads it (AD8232 Datasheet and Product Info); use nb when pup's egress is flagged"), },- symptoms=["'Access Denied' + 'Reference #18.3351db17...'", "typeof bmak === undefined on the denied page (rejected upstream)", "HTTP/2 stream reset to curl"],+ symptoms=["'Access Denied' + 'Reference #18.3351db17...'", "HTTP 403 from AkamaiGHost on the denied request (refused at the edge, before JS)", "HTTP/2 stream reset to curl"], recipes=[ ("Load the site in pup", "Requires CfT matched to the installed Chrome (pup 2.0.549+, CfT 152). If it still denies with bmak undefined, the egress IP is flagged: use nb, or a box on a VPN/residential/cloud IP. Clear cookies first if it denied you earlier: pup_clear_cookies {domain:'analog.com'}."), ("Datasheet PDF", "/media/en/technical-documentation/data-sheets/<part>.pdf; nbrowser_fetch_url once you have the link, or pup on a clean egress."),@@ -367,6 +367,45 @@ def lane_table(site): rows.append(f"| {L} | **{r}** | {note or '-'} |") return "\n".join(rows) +# ---------------------------------------------------------------------------+# 2026-09-14 PACED RE-VERIFICATION (layered over the 2026-09-12 sweep above).+# Conditions: pup 2.0.549, Chrome for Testing 152 (matched to the installed+# Chrome), EXTENSION lane (no debug port), consumer identity on, ONE tab at a+# time with a 7 s settle, that domain's cookies cleared first, AdomLapper on a+# corporate VPN egress. Result: 20 of 20 loaded, including the four the earlier+# BURST run called blocked. The burst was tripping velocity rules; it was not+# the sites refusing pup. The 09-12 notes are kept because they are the failure+# SIGNATURES: that is what these sites look like when the conditions above are+# not met (stale CfT, unpaced requests, a poisoned verdict cookie).+# ---------------------------------------------------------------------------+PACED = {+ "st": "loads paced on CfT 152. On CfT 148 this was ERR_HTTP2_PROTOCOL_ERROR after the first page; the version match is what fixed it",+ "mouser": "HOME PAGE loads paced on CfT 152 (was 'Access to this page has been denied' on 148). DataDome still scores CRAWLS: use the API for data, do not walk the catalog",+ "digikey": "loads paced on CfT 152",+ "arrow": "loads paced on CfT 152. Earlier BLOCKED readings came from the 20-tab burst, not from arrow",+ "analog": "loads paced on CfT 152 (bmak:object, i.e. the real page with the sensor on it was served). On CfT 148 the edge answered HTTP 403 before any JS ran: the version match is the fix, and the refusal was on the connection fingerprint, not a sensor failure",+ "ti": "loads paced on CfT 152",+ "microchip": "loads paced on CfT 152",+ "nordic": "loads paced on CfT 152",+ "snapeda": "loads paced on CfT 152",+ "ultralibrarian":"loads paced on CfT 152",+ "componentsearchengine": "loads paced on CfT 152",+ "datasheets-com":"loads paced on CfT 152. Earlier BLOCKED reading came from the burst",+ "octopart": "loads paced on CfT 152",+ "jlcpcb": "loads paced on CfT 152 (LCSC too)",+ "avnet": "loads paced on CfT 152, root and /americas/. The PR_WAF_DENY reCAPTCHA page is a VELOCITY deny: a 20-tab burst trips it and the verdict sticks until cookies are cleared",+ "newark": "loads paced on CfT 152",+ "rs-online": "loads paced on CfT 152",+ "infineon": "loads paced on CfT 152",+ "nxp": "loads paced on CfT 152",+}+for _s in SITES:+ _n = PACED.get(_s["slug"])+ if _n:+ _s["lanes"]["pup"] = ("OK", _n + " [paced re-verification 2026-09-14]")+ _s.setdefault("gotchas", []).insert(0,+ "Verified loading 2026-09-14 under: CfT 152 + extension lane + PACED single visit + that domain's cookies cleared. Change any one of those (stale CfT, a burst of tabs, a stale reject cookie) and the failure signatures below come back. The signatures are kept for recognition, not because the site is currently blocking pup.")+ def site_skill(site): name = SKILL_PREFIX + site["slug"] doms = ", ".join(site["domains"])@@ -450,15 +489,19 @@ Browser Extension 0.16.14 (Chrome 152). Two independent discoveries this date, each measured, that reframe the hardest Akamai sites: **1. The Chrome-for-Testing VERSION is itself a bot signal.** pup pinned CfT 148 while the user's-real Chrome was 152. On 148, Akamai's `bmak` sensor never initialised (`typeof bmak === "undefined"`-on every load) and analog.com served Access Denied. On CfT **152** (matched to the installed Chrome)-the sensor initialises (`typeof bmak === "object"`), runs, and the page loads. It was NOT a fingerprint-match (the JA4 still differs from branded Chrome); Akamai gated on the sensor being able to EXECUTE,-which a 4-version-old build broke. Keep CfT within ~1 milestone of the installed Chrome. Several sites+real Chrome was 152. On 148, analog.com answered **HTTP 403 (AkamaiGHost)** with a static Access Denied+page; on CfT **152** (matched to the installed Chrome) the same URL serves the real page. Be precise+about where that is decided: a 403 arrives at the HTTP layer, so the edge refused the REQUEST and no+page JavaScript ever ran. CfT 148 executes JavaScript fine; that was never the issue. The discriminator+is the CONNECTION fingerprint (the TLS ClientHello measurably differs between CfT builds). Which exact+element flips the verdict has NOT been isolated. `typeof bmak === "undefined"` on a denied page is a+SYMPTOM, because the Access Denied page carries no sensor script at all. Keep CfT within ~1 milestone of the installed Chrome. Several sites that were pup-BLOCKED on 148 (st.com among them) load on 152. Diagnostic on a denial: `typeof bmak` `undefined` = rejected upstream (version or IP); `object` = the sensor ran and failed you (IP/behaviour). -**2. Egress IP reputation is a separate, stacked cause.** Same CfT 152, same code, four boxes:+**2. Egress IP reputation: SUSPECTED, not established.** The four-box comparison below was run with+the BURST method, which we now know trips velocity rules on its own, so these readings are method-suspect+and have not been reproduced paced. Treat as a hypothesis to re-test, not as fact: AdomLapper (corporate VPN egress) and winvm (Azure) LOAD analog.com; arav-rog and ConfRoomROG (bare office LAN) are DENIED. Identical browser, opposite result: the bare office NAT IP is Akamai-flagged. pup cannot fix this from inside the browser; the lever is a cleaner egress (VPN/residential/cloud) or@@ -483,6 +526,24 @@ masks a fix. *Mouser loads its home page but scores behaviour on crawls (DataDome) - use the API for data. +## How to load ANY of these in pup (the procedure that got 20 of 20)++Measured 2026-09-14 on AdomLapper: all twenty sites in this pack loaded in pup, including the four a+previous burst run had called blocked. Three conditions, all of them required:++1. **Match Chrome for Testing to the user's INSTALLED Chrome.** Check `pup_readiness.chromeBuildId`+ against their Chrome. A stale CfT breaks Akamai's sensor outright (it never initialises) and no+ header work rescues it.+2. **Go at human pace: ONE tab at a time, with a real settle (about 7 s).** A burst of tabs trips+ velocity rules on Akamai sites (avnet, arrow, datasheets all "blocked" purely from bursting). This+ is the single most common self-inflicted block.+3. **Clear that domain's cookies before the visit.** A previous denial writes a reject verdict that+ persists and will keep denying you long after the real cause is fixed.++Then use the default extension lane (no debug port) with the consumer identity on, which is what+`pup_open_window` already does. Only when all three conditions hold and a site STILL refuses is it+worth reaching for nb or the API lane.+ ## The rule: a fetch failure on a vendor domain is a ROUTING signal 1. **One plain attempt only.** WebFetch or curl once. It is the cheapest lane and it works on TI,@@ -639,7 +700,7 @@ def main(): {"label": "Which browser for DigiKey", "prompt": "which browser lane do I need to read a DigiKey product page"}, {"label": "Mouser 200 but denied", "prompt": "why does Mouser return HTTP 200 with access denied and what do I do"}, {"label": "Add a site", "prompt": "add an electronics-sites skill for nxp.com and verify its lanes"}]- pkg = {"name": PACK, "slug": PACK, "version": "2.1.1", "type": "skill", "title": TITLE, "description": BRIEF,+ pkg = {"name": PACK, "slug": PACK, "version": "2.2.0", "type": "skill", "title": TITLE, "description": BRIEF, "license": "MIT", "files": files, "scripts": {"install": "./install.sh", "uninstall": "./uninstall.sh"}, "dependencies": {}, "tags": TAGS, "keywords": TAGS, "discovery_triggers": TRIGGERS, "discovery_pitch": PITCH, "sample_prompts": PROMPTS, "hero": {"path": "docs/hero.png"}}@@ -687,7 +748,7 @@ No captcha solving, no fingerprint spoofing: this pack routes around walls, it d """ write("README.md", readme) page = json.load(open(os.path.join(ROOT, "page.json")))- page.update({"slug": PACK, "version": "2.1.1", "title": TITLE, "brief": BRIEF, "readme": readme, "license": "MIT",+ page.update({"slug": PACK, "version": "2.2.0", "title": TITLE, "brief": BRIEF, "readme": readme, "license": "MIT", "tags": TAGS, "hero": {"type": "image", "path": "docs/hero.png"}, "sample_prompts": PROMPTS, "discovery_triggers": TRIGGERS, "discovery_pitch": PITCH,