How to Find and Scrape Hidden APIs With Browser DevTools
Advanced Data Extraction Specialist
TL;DR:
- A hidden API is a request the page uses but does not advertise as a public developer API. It may return JSON, GraphQL data, HTML fragments, or a stream consumed by the frontend.
- Browser DevTools reveals the request contract. Record the page action, filter Fetch/XHR, inspect the URL, method, query, payload, response, initiator, and pagination behavior.
- Reproduce only public or authorized requests. Stop when the request depends on login, private data, access-control tokens, or a use prohibited by the site's terms.
- Keep the browser as a discovery and fallback layer. An internal endpoint can change without notice, and some requests require cookies or state established in the same browser session.
- Validate fields and page identity. A successful status is not enough; check the expected schema, locale, pagination cursor, and required public records.
Many JavaScript pages fetch their real content after the document loads. The rendered cards are only one presentation of a structured response already visible in the browser's Network panel.
Scraping hidden APIs means observing those browser-initiated requests and, where the data is public or explicitly authorized, reproducing the smallest stable request contract. It does not mean discovering private endpoints, defeating authentication, or extending a page's privileges.
What Is a Hidden API?
A hidden API is an internal HTTP or WebSocket interface used by a site's own frontend without being presented as a supported public API. The endpoint may be undocumented and can change whenever the frontend changes.
Common response shapes include:
- JSON objects or arrays;
- GraphQL response envelopes;
- HTML fragments inserted into the page;
- newline-delimited event streams;
- binary formats that require the site's own decoder.
The phrase describes discoverability, not permission. A request visible in a browser can still carry account state, personal data, licensed content, or contractual restrictions. Keep the workflow within public or authorized surfaces.
DOM Scraping vs Internal JSON Requests
The right source is the one that returns the approved fields with the smallest stable contract.
| Question | DOM extraction | Internal request extraction |
|---|---|---|
| Data format | HTML elements and attributes | Often structured JSON or GraphQL |
| Discovery | Inspect rendered page | Inspect Network activity |
| Sensitivity to redesign | CSS and DOM changes | Endpoint and schema changes |
| Browser requirement | Required for client rendering | Often required for discovery or session state |
| Pagination | Clicks, scroll, next links | Page, offset, cursor, or request payload |
| Best use | Data exists only in presentation | Stable public fields appear in a structured response |
Use the DOM when the page's own presentation is the authoritative source or when the request contract is too fragile. Use an internal response when it exposes the required public fields cleanly and the workflow can honor the same access boundaries.
Step 1 — Open DevTools Before the Page Action
The Network panel only records requests made while it is open. Open DevTools, select Network, enable Preserve log when navigation is involved, and clear the existing list.
The Chrome DevTools Network reference documents Preserve log, request-type filters, payload inspection, response previews, initiators, HAR export, and Copy as fetch or cURL.
Now perform one action that loads the data:
- submit one public search;
- switch one category;
- load the next result page;
- expand one public detail panel;
- scroll until the next batch appears.
One action creates a smaller, auditable request diff than interacting with the whole page first.
Step 2 — Filter Fetch/XHR and Find the Data-Bearing Response
Select Fetch/XHR, then inspect requests whose timing aligns with the page action. Search response bodies for one stable public value visible on the page, such as an item ID, exact title, or category code.
Check these fields:
| DevTools field | What to capture | Why it matters |
|---|---|---|
| Request URL | Origin, path, and query | Defines the route and page parameters |
| Method | GET or POST | Determines where parameters live |
| Payload | Query string, form data, or JSON | Carries filters and cursors |
| Response | Top-level schema and required fields | Confirms the request contains the target data |
| Initiator | Script or call stack | Shows which page action created it |
| Headers | Content type and necessary public context | Distinguishes representation and locale |
| Timing | Start and duration | Helps correlate request with the action |
Do not copy every browser header. Start from method, URL, payload, and documented public context. Add a header only when a controlled test proves the request contract needs it.
Step 3 — Decide Whether the Request Is Safe to Reproduce
A reproducible request must stay inside the same authorization boundary as the page.
Proceed when:
- the response contains public data the user can access without an account;
- the request is part of an explicitly authorized integration or test;
- the intended volume is proportionate;
- the fields are necessary for the stated dataset.
Stop when:
- the response exposes private or account-scoped data;
- reproduction would cross a login, paywall, or access-control boundary;
- the request depends on a secret that is not yours to use;
- the site's terms or the project's approval do not permit the activity.
The Chrome HAR export guidance notes that sanitized exports omit sensitive headers such as Cookie, Set-Cookie, and Authorization. Use sanitized captures for documentation unless the approved debugging task specifically requires protected values.
Step 4 — Copy the Request, Then Reduce It
DevTools can copy a request as cURL or as a Node.js fetch call. Treat that output as a diagnostic snapshot, not production code.
Remove in this order:
- tracking and browser-generated headers;
- cookies unrelated to the public representation;
- one-off correlation values;
- parameters that do not change the required result;
- redundant content negotiation headers.
After each change, validate the response schema and required records. The goal is a minimal request contract that can be explained field by field.
The browser's Fetch API treats cookies and authentication headers as credentials. The MDN Fetch API guide explains how credential handling interacts with cross-origin requests. Do not carry credentials into a standalone script unless the job is explicitly authorized and the storage and access model has been reviewed.
Step 5 — Map the Response Into a Stable Schema
Internal responses often expose more fields than the dataset needs. Define a narrow output contract.
json
{
"source_url": "https://example.com/public-search?q=notebook",
"query": "notebook",
"page": {
"cursor": "next-public-cursor",
"has_more": true
},
"items": [
{
"id": "item-123",
"title": "Illustrative public result",
"url": "https://example.com/public/items/item-123",
"price": null
}
]
}
The schema above is an illustrative sample. Keep nullable fields nullable, retain the source URL, and preserve a stable identifier when the response supplies one.
Start a free Scrapeless Scraping Browser session when discovery requires JavaScript and browser state.
Step 6 — Understand Pagination Before Scaling
Pagination usually appears in one of four places:
- a
pagenumber in the query; - an
offsetplus a fixed limit; - an opaque cursor in the response;
- a GraphQL variable in the request body.
Trigger exactly one next-page action and compare the two requests. Record which value changed and which response field provides the next value. Do not invent or decode opaque cursors.
Use a stopping rule tied to the contract: has_more becomes false, the next cursor is absent, the result array is empty, or the approved maximum page count is reached. Deduplicate on a stable public ID rather than title text.
Step 7 — Keep Session State When the Request Needs It
Some internal requests work only after the page establishes cookies, consent, locale, or another allowed state. In that case, keep discovery and extraction in one bounded browser session.
Scrapeless Scraping Browser runs JavaScript in a cloud browser and keeps session state across approved navigation. Use it to observe the request and extract the response from the same context rather than exporting opaque state into an unrelated client.
The Scrapeless Scraping Browser documentation documents bounded session lifetimes and geographic routing parameters. Keep geography, language, cookies, and page sequence fixed while validating the request.
Browser Fallback: When the Internal API Is the Wrong Source
The browser remains the safe fallback when the internal endpoint is unstable, account-scoped, heavily coupled to ephemeral state, or missing presentation-dependent fields.
Choose rendered DOM extraction when:
- the response schema changes more often than semantic page elements;
- a public field is computed only after client rendering;
- the endpoint's authorization model is unclear;
- replaying the request would require copying sensitive credentials;
- the page's visible representation is the dataset of record.
The JavaScript rendering guide explains the difference between initial HTML, client-rendered content, and asynchronous requests.
Troubleshooting Hidden API Scraping
| Observation | Likely explanation | Check |
|---|---|---|
| Response is HTML, not JSON | Redirect, challenge, consent, or error representation | Final URL, content type, title, body marker |
| JSON has empty items | Wrong locale, missing public parameter, or end of pagination | Compare the working browser request and page state |
| Fields disappear | Schema drift or conditional result type | Preserve nullable fields and validate each item type |
| Cursor repeats | Wrong cursor source or cached request | Read the next cursor from the current accepted response |
| Standalone request is rejected | Browser session state is required | Keep extraction inside the authorized browser context |
| DOM and JSON counts differ | UI filtering, personalization, or extra response records | Define which representation is authoritative |
Change one variable at a time and save a sanitized example of the accepted response shape. If the request crosses an access boundary, stop instead of adjusting the client.
Conclusion: Treat the Request Contract as a Dependency
Scraping hidden APIs can replace brittle DOM parsing with structured public data, but the endpoint is an internal dependency rather than a supported public contract. Discover it through one page action, reduce the copied request, map only required fields, and document pagination and state.
Keep a browser fallback for schema changes and session-bound flows. Re-check authorization whenever the page, endpoint, or dataset scope changes.
Ready to Build a Browser-Aware Extraction Workflow?
Join the Scrapeless community to discuss public-data discovery and schema design: Discord · Telegram.
Review Scrapeless pricing, then sign up at app.scrapeless.com for free Scraping Browser runtime.
FAQ
Q: Is scraping a hidden API legal?
Scraping an internal request can be lawful when it accesses public or authorized data, but laws, contracts, and facts vary, so review the site's terms and obtain legal advice for the project.
Q: Is a hidden API the same as a public API?
A hidden API is used internally by a frontend and carries no promise of documentation, stability, or third-party access, while a public API is intentionally exposed under a supported contract.
Q: Do you need a proxy to inspect hidden APIs?
A proxy is unnecessary for local DevTools inspection but may be required for an approved location-specific dataset or proportionate collection workflow.
Q: What should you do when an internal request returns an access-denied page?
Stop and inspect the returned representation, authorization boundary, and project scope; do not treat a different header or token as permission.
Q: How do you handle DOM or schema changes?
Re-run one known page action, compare the request and response contract, update nullable mappings, and keep a rendered-DOM fallback for fields the internal response no longer supplies.
Q: How much concurrency should a hidden API scraper use?
Keep concurrency at three or fewer workers per host until the site's published rules, authorization, and observed stability support a higher level.
Q: Can this workflow run without an AI agent?
Yes, DevTools discovery, sanitized request reproduction, schema validation, and browser fallback are deterministic engineering steps that do not require an AI agent.
At Scrapeless, we only access publicly available data while strictly complying with applicable laws, regulations, and website privacy policies. The content in this blog is for demonstration purposes only and does not involve any illegal or infringing activities. We make no guarantees and disclaim all liability for the use of information from this blog or third-party links. Before engaging in any scraping activities, consult your legal advisor and review the target website's terms of service or obtain the necessary permissions.



