From website-to-api
Reverse-engineer a website's internal API using Chrome browser automation. Use when asked to discover, wrap, or build a programmatic interface for a website that doesn't have a public API. Guides the process of finding endpoints, extracting auth, and building scripts.
npx claudepluginhub hamelsmu/website-to-apiThis skill uses the workspace's default tool permissions.
A systematic approach to discovering and wrapping any website's internal API using Chrome browser automation (Claude in Chrome extension).
Reverse engineers web APIs from browser-captured HAR files using Playwright, generating production-ready Python clients. Useful for undocumented APIs, web automation, or traffic analysis.
Captures HTTP traffic from web apps using Playwright CLI with site fingerprinting for frameworks, protections, iframes, auth, APIs, plus tracing and HAR export. For API discovery and site analysis.
Share bugs, ideas, or general feedback.
A systematic approach to discovering and wrapping any website's internal API using Chrome browser automation (Claude in Chrome extension).
substack) has broken and needs re-discoveryEvery modern web application fetches data from internal API endpoints. This skill teaches a repeatable 4-step process to discover and wrap those endpoints.
Navigate to the target website using the Chrome extension and observe what API calls the page makes.
Tools needed:
ToolSearch("select:mcp__claude-in-chrome__tabs_context_mcp,mcp__claude-in-chrome__navigate,mcp__claude-in-chrome__javascript_tool,mcp__claude-in-chrome__read_network_requests,mcp__claude-in-chrome__get_page_text,mcp__claude-in-chrome__read_page")
Procedure:
Get tab context and navigate:
mcp__claude-in-chrome__tabs_context_mcp(createIfEmpty=true)
mcp__claude-in-chrome__navigate(url="https://target-site.com", tabId=TAB_ID)
Enable network tracking, then trigger actions:
mcp__claude-in-chrome__read_network_requests(tabId=TAB_ID) // starts tracking
Navigate or interact with the page to trigger API calls, then read:
mcp__claude-in-chrome__read_network_requests(tabId=TAB_ID, urlPattern="api")
Inspect page globals for config:
// Run via javascript_tool — look for app config, API base URLs, user info
JSON.stringify(Object.keys(window).filter(k =>
k.includes('config') || k.includes('api') || k.includes('app') || k.startsWith('__')
));
Check for framework data (Next.js, etc.):
// Next.js apps embed data in __NEXT_DATA__
const nd = document.getElementById('__NEXT_DATA__');
nd ? JSON.stringify(Object.keys(JSON.parse(nd.textContent))) : 'not Next.js';
Try common API patterns:
// Most sites use /api/v1/ or similar
fetch('/api/v1/...', { credentials: 'include' })
.then(r => r.json())
.then(data => { document.title = JSON.stringify(Object.keys(data)); });
Document what you find — endpoints, parameters, response shapes.
Most sites use httpOnly session cookies that JavaScript cannot read. The browser sends them automatically with fetch() using credentials: 'include'.
Verify auth works:
// Run via javascript_tool on the target site
fetch('/api/v1/some-endpoint', { credentials: 'include' })
.then(r => r.json())
.then(data => { document.title = JSON.stringify({ authenticated: true }); })
.catch(e => { document.title = 'ERROR: ' + e.message; });
Compare auth vs no-auth:
# Unauthenticated (from terminal)
curl -s 'https://target-site.com/api/v1/endpoint' | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(str(d)))"
Compare the response size/content with the browser-based fetch to identify what auth adds.
Find the cookie name:
window._analyticsConfig or similar globals for site metadataconnect.sid, {site}.sid, session, _session_idFor script usage, the user must extract the cookie value once:
export SITE_AUTH_COOKIE="<value>"Create a Python CLI script using PEP 723 inline metadata (runs via uv run, no install needed).
Script template: See templates/site-skill-template/scripts/client.py.template
Key principles:
httpx for HTTP, typer for CLI, rich for display, markdownify for HTML→MD--sid/--cookie flagget-text command that fetches content and saves as MarkdownCreate a SKILL.md that documents:
Every site-specific skill MUST include this section:
## If This Breaks
This skill uses an internal, undocumented API. If commands fail:
1. Read the error — 401/403 likely means expired cookie or renamed cookie
2. Re-discover using the `website-to-api` meta-skill
3. Update this skill's SKILL.md and scripts with the new API shape
document.title (which truncates and corrupts data)get_page_text for extracting rendered page content — it's simpler than transferring HTML through JavaScriptdocument.title for data larger than ~500 chars — it truncates silently and causes data corruption