# Browser API Response Shape Drift Monitor (`produkdigitalali/browser-api-response-shape-monitor`) Actor

Detect structural and primitive-type changes in JSON responses used by public browser pages without storing payload values or field names.

- **URL**: https://apify.com/produkdigitalali/browser-api-response-shape-monitor.md
- **Developed by:** [ProdukDigitalAli](https://apify.com/produkdigitalali) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$15.00 / 1,000 api response shape page checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Browser API Response Shape Drift Monitor | Playwright

Observe the JSON responses a public page actually uses, then compare their sampled structure and primitive types against a persistent baseline. Detect schema drift without exporting payload values, JSON field names, headers, cookies, or request bodies.

### Quick start

```json
{
  "urls": ["https://googlechrome.github.io/samples/fetch-api/fetch-json.html"],
  "monitorKey": "public-api-daily",
  "captureMs": 2000,
  "navigationTimeoutSeconds": 25,
  "maxResponses": 20,
  "maxChanges": 50,
  "resetBaseline": false
}
```

First run: BASELINE_CREATED. Later runs with the same monitorKey and exact page/endpoint URL: UNCHANGED or CHANGED. Values changing while types stay stable do not create drift. Set resetBaseline true only when intentionally accepting a new structure.

### Use cases

- Catch JSON type and structural regressions after a frontend/API deployment.
- Monitor anonymous browser data feeds before a scraper integration breaks.
- Add scheduled response-shape checks alongside HAR traffic diagnostics.
- Identify which browser-observed endpoint shape changed without retaining personal data.

### What it captures

GET responses with JSON content types from document, XHR, or fetch traffic. Only successful responses up to 256 KiB are accepted. Repeated identical endpoint URLs are grouped and their type observations merged. Credential-bearing and common account/authentication endpoints are skipped. POST/PUT/DELETE and other mutations are blocked, so GraphQL POST traffic is unsupported.

### Input and limits

| Field | Default | Limit / behavior |
| --- | --- | --- |
| urls | Official GoogleChrome fetch sample | 1-5 public HTTP(S) page URLs |
| monitorKey | public-api-daily | 3-64 safe letters, digits, hyphens, underscores |
| captureMs | 2000 | 0-10,000 ms after DOM readiness |
| navigationTimeoutSeconds | 25 | 5-45 seconds |
| maxResponses | 20 | 1-40 JSON samples per page |
| maxChanges | 50 | 1-200 change examples per endpoint |
| resetBaseline | false | Accept this run as a new baseline |

Every page has a 16 MiB network transfer limit, 200 connections, and 10 seconds for body processing. Shapes sample up to 100 array items, 500 distinct paths, 5,000 nodes, and depth 12 per response. Truncated or capped captures are marked. No credentials, cookies, proxy configuration, custom scripts, or headers are accepted.

### Output

One dataset row per page. CHECKED contains endpoints with BASELINE_CREATED, UNCHANGED, or CHANGED. NO_JSON_RESPONSES is a free diagnostic result. ERROR indicates capture/storage failure and is free. If all pages fail, the run fails after storing error rows.

Endpoint records contain endpointId, origin, current/previous shape hash, path count, response count, baseline key, truncated flag, change count, and capped added/removed/type-changed paths. Page paths and JSON keys are hashed. Query strings and body values never persist. The OUTPUT record summarizes succeeded, failed, and charged pages.

Baselines are kept in the account's named key-value store browser-api-response-shape-baselines. Preserve it for scheduled checks. Keys combine monitorKey, exact page URL, and endpoint URL identity. Avoid concurrent runs for the same monitorKey; storage follows last-writer semantics.

### Privacy-safe paths

A structural path looks like $/k:HASH/\[]/k:HASH. Property tokens are the first 16 hexadecimal characters of SHA-256 over the JSON property name; endpointId hashes GET plus the exact URL. Developers who know their API keys can compute the same tokens locally. This deliberate redaction is less readable than raw schema names but protects arbitrary dynamic keys and identifiers.

### Pricing proposal

Standard tier: USD 0.015 per api-shape-page-checked event. Charged only when a page yields at least one accepted JSON shape, the dataset report is stored, and every associated baseline is stored. No charge for failed or no-JSON pages. First baseline creation is one useful check. Platform compute/storage costs depend on the user's Apify plan. The cloud listing uses PAY_PER_EVENT pricing at USD 0.015 per successfully stored page check.

### Sample inference limitations

This reports observed shape drift, not a full JSON Schema or OpenAPI validity/breaking-change verdict. Empty arrays, nulls, optional fields and changing samples can cause drift. Missing traffic does not prove an endpoint was removed. Fresh browser contexts can miss authenticated, interactive, lazy or service-worker requests. Endpoint queries changing produce distinct identities. Capture does not click, scroll or replay APIs. It does not certify privacy compliance or guarantee scraping reliability.

### Suggested tasks

- Daily browser API shape regression: stable key, reset false.
- Release baseline approval: reset true once, then false.
- Focused anonymous integration watch: one page and a short capture window.

### Local execution

Install Node 22+ and Chromium. Set APIFY_CHROME_EXECUTABLE_PATH to the browser executable locally, install locked dependencies, then npm test. Store input in storage/key_value_stores/default/INPUT.json and run npm start. Docker pins the Playwright Chrome base image; local smoke uses the installed Chrome.

# Changelog

This Actor's version history is a separate document: https://apify.com/produkdigitalali/browser-api-response-shape-monitor/changelog.md

# Actor input Schema

## `urls` (type: `array`):

One to five public pages that load JSON in browser network traffic.

## `monitorKey` (type: `string`):

Stable label to reuse per-page endpoint baselines across runs.

## `captureMs` (type: `integer`):

Wait after initial DOM load for JSON fetch/XHR responses.

## `navigationTimeoutSeconds` (type: `integer`):

Maximum navigation time per page.

## `maxResponses` (type: `integer`):

Maximum response samples; repeated endpoints are merged.

## `maxChanges` (type: `integer`):

Maximum hashed structural paths in each endpoint diff.

## `resetBaseline` (type: `boolean`):

Accept the current structure as a new baseline.

## Actor input object example

```json
{
  "urls": [
    "https://googlechrome.github.io/samples/fetch-api/fetch-json.html"
  ],
  "monitorKey": "public-api-daily",
  "captureMs": 2000,
  "navigationTimeoutSeconds": 25,
  "maxResponses": 20,
  "maxChanges": 50,
  "resetBaseline": false
}
```

# Actor output Schema

## `summary` (type: `string`):

No description

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        "https://googlechrome.github.io/samples/fetch-api/fetch-json.html"
    ],
    "monitorKey": "public-api-daily"
};

// Run the Actor and wait for it to finish
const run = await client.actor("produkdigitalali/browser-api-response-shape-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "urls": ["https://googlechrome.github.io/samples/fetch-api/fetch-json.html"],
    "monitorKey": "public-api-daily",
}

# Run the Actor and wait for it to finish
run = client.actor("produkdigitalali/browser-api-response-shape-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    "https://googlechrome.github.io/samples/fetch-api/fetch-json.html"
  ],
  "monitorKey": "public-api-daily"
}' |
apify call produkdigitalali/browser-api-response-shape-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,produkdigitalali/browser-api-response-shape-monitor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/MDVszkCHqEMjkuu8w/builds/hlVbglOHApPhwbTW4/openapi.json
