Subprocessor Change Monitor
Pricing
$50.00 / 1,000 checks
Subprocessor Change Monitor
Watch vendor subprocessor pages and get alerted when subprocessors are added, removed, or changed.
Pricing
$50.00 / 1,000 checks
Rating
0.0
(0)
Developer
Virtual Constructs
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Watch any vendor's subprocessor page and get alerted the moment a subprocessor is added, removed, or changed. This is the recurring GDPR Article 28 chore, the one where you are supposed to review each vendor's sub-processor list for changes, turned into a scheduled, pay-per-use monitor that runs itself.
You supply the URLs (you know your own vendors); the monitor fetches each page, parses the subprocessor list, and diffs it against the last run. Every run returns only what changed. Output is a stable, documented JSON schema, easy to wire into alerts, tickets, compliance workflows, and AI agents (MCP-friendly).
This is a monitor, not a platform: one dumb reliable pipe. No dashboard, no posture score, no policy templates. It watches pages and tells you what moved. Continuous sub-processor assurance across a 20-vendor list runs about $30 a month (see costs below), far less than doing the review by hand or than learning late that a vendor changed who processes your data.
What does it return?
One dataset item per URL per run:
changedandchangeType(list,content, ornone)added[]andremoved[]: subprocessors that appeared or disappeared, each withname,purpose,location, and the raw row textchangedEntries[]: subprocessors present in both runs whose purpose, location, or text changed (before/after)currentList[]: the full normalized subprocessor list parsed this runcontentHash,snapshotRef,checkedAt, andok/error
How to monitor subprocessor changes
- Paste the vendor subprocessor page URLs you want to watch, e.g.
https://stripe.com/legal/service-providers. - Set a Monitor name and put the actor on a schedule (daily or weekly is typical). The first run per URL establishes a baseline; every later run returns only what changed.
- Results land in the dataset as JSON, CSV, or Excel. Wire a webhook or a
Slack/email integration to the run to get alerted on
changed: true.
That is the whole product: point it at the pages, schedule it, get diffs.
Input
| Field | Type | Default | Notes |
|---|---|---|---|
urls | array | required | Vendor subprocessor page URLs to watch (you supply them). |
mode | string | auto | auto parses a structured list when found, else text. list / text force it. |
notifyOn | string | list-change-only | list-change-only ignores page-chrome noise; any-change flags any text change. |
selectorByUrl | object | {} | Optional { "url": "cssSelector" } to pin the exact content region. |
monitorName | string | default | Names this watchlist's saved state; enables run-to-run diffing. |
maxConcurrency | integer | 5 | Pages fetched in parallel (kept polite). |
proxyConfiguration | object | Apify Proxy on | Spreads requests across IPs; improves reach on rate-limited hosts. |
Managed monitoring: set a name, schedule it, done
Set monitorName (e.g. "my-vendors") and the actor keeps a small snapshot
per URL in a key-value store in your Apify account. Every scheduled run diffs
each page against the last run:
- First run for a URL: establishes the baseline (
baseline: true, no change reported). - Every later run: reports
added/removed/changedEntriesif the list moved, otherwisechanged: false. - Changing a URL's
selectorByUrlor the diffmodere-baselines that URL (the content region is no longer comparable).
Use different monitor names for independent watchlists. No cursor management, no state of your own.
Output example
{"url": "https://acme.com/legal/subprocessors","checkedAt": "2026-07-13T16:00:00.000Z","ok": true,"changed": true,"changeType": "list","baseline": false,"added": [{"name": "Twilio, Inc.","purpose": "SMS delivery","location": "US","raw": "Twilio, Inc. | SMS delivery | US"}],"removed": [],"changedEntries": [],"currentList": [{"name": "Amazon Web Services, Inc.","purpose": "Hosting","location": "US","raw": "Amazon Web Services, Inc. | Hosting | US"}],"entryCount": 24,"path": "list","contentHash": "9f2c1a5b7d3e4c6a8b0f2d1e3c5a7b9d0e2f4a6c","snapshotRef": "my-vendors--3a1f8c2b9d4e6f0a","error": null,"source": "subprocessor-monitor"}
Every field is always present; missing data is null, never an absent key.
New fields may be added in future versions; existing fields will not change
shape.
Result status and error codes
Every record has an ok flag and an error field. When ok is true, the
page was fetched and diffed and error is null. When a URL cannot be
checked, ok is false, error says why, and that URL is not charged. The
full set of error codes:
error | What it means | Charged? |
|---|---|---|
null | Success: the page was fetched and diffed. | Yes |
js-rendered | The page is a JavaScript-only shell (SafeBase, Vanta-hosted trust center, etc.); the list is not in the server HTML. | No |
no-content-region | The page loaded with real content, but no usable subprocessor region was found (unusual markup, or a selectorByUrl that matched nothing). | No |
non-html | The response was a PDF or other non-HTML document. | No |
http-error | The server returned a 4xx/5xx status (blocked, moved, rate-limited, or down). | No |
fetch-failed | The request failed to complete (network error, DNS, or timeout). | No |
charge-limit | Your run's spending limit was hit before this URL. It is left unchecked and picked up on the next run. | No |
Only null (a successful check) is billed. Everything else is free, so a run
where nothing could be checked costs nothing.
Who is this for?
Privacy and DPO teams meeting GDPR Article 28 sub-processor review duties, GRC and vendor-management teams tracking their supply chain, procurement and security reviewers, and AI agents that need vendor subprocessor changes as clean structured JSON instead of scraping HTML tables themselves. It also works for competitive and market research: watch what vendors your competitors add.
If your GRC platform already tracks the subprocessors of tools it integrates with, this covers the vendors it does not: any company with a public subprocessor page, a la carte, pay-per-use, callable from a pipeline or agent.
Why monitor subprocessor changes?
Under GDPR Article 28, a data processor must keep a current list of its sub-processors and give customers advance notice and a chance to object before it adds or replaces one. Your Data Processing Agreement (DPA) with each vendor usually points at that subprocessor page as the source of truth. The catch is that the notice does not always reach you: pages change quietly, update emails land in an unwatched inbox, and whoever owns vendor risk often finds out at audit time instead of when it happened.
Watching each vendor's sub-processor list is also a recurring control in the
frameworks your customers ask about: SOC 2 and ISO 27001 vendor and
third-party risk management, CCPA/CPRA service-provider disclosures, and
general supply-chain due diligence. A new sub-processor can mean a new country
of data processing, a new AI vendor touching customer data, or a fourth party
you never assessed. Catching the change on the day it ships, with a structured
added / removed diff, is the difference between a proactive review and an
awkward finding.
This actor turns that standing chore into a scheduled job: a subprocessor change monitor and alert across your whole vendor watchlist, with no subscription and no platform to adopt.
Monitor your own subprocessor page too
You can point it at your own company's subprocessor / sub-processor page, not just your vendors'. That catches your published list drifting from reality: a hosting migration your team shipped, an analytics or AI vendor added without updating the page, or an edit that should have triggered customer notice under your own DPA. It is a cheap standing check that your public sub-processor disclosure still matches what you actually run, which is exactly what an auditor or a security-conscious prospect will look at.
How much does it cost?
Pay per event: $0.05 per URL checked, and nothing else. No subscription, no seat licences, no charge for pages that could not be checked, no charge for empty runs.
What that buys, in practice:
- A 20-vendor watchlist, checked daily: about $30 a month (roughly 600 checks). That is continuous GDPR Article 28 sub-processor monitoring across your whole vendor list, running itself, for less than an hour of a privacy analyst's time.
- Ten vendors, weekly: around $2 a month.
- A one-off audit of 50 vendors: $2.50 for the run.
Compare that to doing it by hand (someone opening each vendor's page on a calendar reminder and eyeballing the table for changes), or to the price of finding out late that a vendor quietly added a sub-processor you never got to object to. The check is the product: you are paying to have the pages watched on a schedule, not only for the runs that happen to surface a change.
maxConcurrency affects speed, not price; the price is per URL per run, and
pages that come back ok: false are free.
Using it from code and agents
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_API_TOKEN>")run = client.actor("virtual-constructs/subprocessor-change-monitor").call(run_input={"urls": ["https://stripe.com/legal/service-providers","https://www.atlassian.com/legal/sub-processors",],"monitorName": "my-vendors",})for item in client.dataset(run["defaultDatasetId"]).iterate_items():if item["changed"]:print(item["url"], item["added"], item["removed"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });const run = await client.actor('virtual-constructs/subprocessor-change-monitor').call({urls: ['https://stripe.com/legal/service-providers'],monitorName: 'my-vendors',});const { items } = await client.dataset(run.defaultDatasetId).listItems();
AI agents can call this actor as an MCP tool via Apify's MCP server (mcp.apify.com). The input and output schemas are stable and documented, so a call like "tell me if any of these vendors changed their subprocessors" works without the agent knowing anything about page markup.
Limits, stated plainly
- Static pages only, in this version. The monitor reads server-rendered
HTML with a fast HTTP fetch. Subprocessor lists hosted on JavaScript-only
trust centers (SafeBase, Vanta-hosted trust pages, and similar) come back as
ok: falsewitherror: "js-rendered"rather than a wrong answer. In a sample of 27 real vendor pages, about 70% were readable this way; the rest were JS-rendered, PDF-only, or bot-protected. Browser rendering for the JS-only pages is planned as a later, separately-priced tier. - A few otherwise-static pages inject the list with JavaScript. If the page
has enough static text to look real but the subprocessor list itself is
rendered client-side (Twilio is one example), the monitor falls back to
watching the page text and reports
path: "text", soentryCountwill be 0 and you will not get per-vendoradded/removed. Checkpathon a new URL: if it is"text"when you expected a list, that page needs the browser tier. - You supply the URLs. The actor does not discover a company's subprocessor page for you. This is deliberate: it removes the fuzziest, most brittle part of the problem and keeps the monitor reliable. You know your vendors; paste their pages.
- Change detection, not legal judgement. It tells you a subprocessor was added, removed, or edited. It does not assess whether that change matters for your compliance posture. That is your call (and deliberately not ours, for accuracy and liability reasons).
- PDF and non-HTML pages are reported as
ok: falsewithin this version.error: "non-html" - Freshness: data is as of the
checkedAttimestamp on each record. This is a poll on your schedule, not a push feed. - Best effort on messy pages.
list-change-only(the default) and date masking suppress most false positives from page chrome; pin the exact region withselectorByUrlif a particular page is still noisy.
FAQ
Why not just check the pages myself? For one or two vendors you can. The paid value is doing it for a whole watchlist on a schedule: fetching, parsing tables and lists into a normalized per-vendor diff, ignoring page-chrome and date noise, remembering the last state so you only see changes, and handing an agent or a no-code schedule a stable tool. Many vendors offer their own "subscribe to subprocessor updates" email, but that is one vendor at a time and email-only; this is one watchlist across any vendor, as structured data.
What is a subprocessor page? A public page where a SaaS vendor lists the third parties (sub-processors) it shares customer data with, e.g. AWS for hosting or Stripe for payments. GDPR Article 28 requires processors to disclose these and give customers a chance to object to changes, so most vendors keep such a page.
How does it avoid false alarms when a page just tweaks its date?
The default notifyOn: list-change-only reports a change only when the
subprocessor list itself changes, and date literals and "last updated" lines
are masked before comparison. Corporate-suffix-only edits (Inc. vs Inc) do
not count as a change either.
A vendor's page did not work. Why?
Most likely it is a JavaScript-only trust center (error: "js-rendered"), a
PDF (error: "non-html"), or it blocked the request (error: "http-error").
The first two are honest current limits; for blocking, enabling Apify Proxy
usually helps.
Can I watch part of a page?
Yes. Put a CSS selector in selectorByUrl for that URL to pin the exact table
or list and ignore the rest of the page.
Which vendors can I monitor? Any company with a public subprocessor page. It works today on the static sub-processor and DPA pages of vendors like AWS, Google Cloud, Stripe, Twilio, Datadog, Atlassian, HubSpot, Cloudflare, MongoDB, Figma, and Zendesk, among many others. You are not limited to a fixed list: paste any vendor's URL and the monitor watches it.
How do I get a Slack, email, or webhook alert when a subprocessor changes?
Attach an Apify integration or a webhook to the run and filter on
changed: true (or on a non-empty added / removed). That turns the actor
into a subprocessor change alert into Slack, email, a ticket, or your own
pipeline, without polling anything yourself.
Does it work with Vanta, SafeBase, or OneTrust trust centers?
Many of those are JavaScript-rendered, so in this version they come back as
error: "js-rendered" rather than a wrong answer (browser rendering for them
is a planned tier). If the same vendor also publishes a static legal or DPA
subprocessor page, point the monitor at that URL instead and it works today.
How often should I check vendor subprocessor pages? Daily or weekly is typical. Because you only pay per check, a daily schedule on a small watchlist is inexpensive, and a weekly one is cheaper still. Pick the cadence that matches your notice-and-objection window.
Does this help with SOC 2, ISO 27001, or CCPA, not just GDPR?
Yes. Sub-processor and third-party vendor monitoring is a recurring control in
SOC 2 and ISO 27001, and CCPA/CPRA has its own service-provider disclosure
obligations. The same added / removed diff is useful evidence for all of
them.
Can AI agents monitor subprocessors automatically? Yes. The actor is MCP-friendly and callable as a tool from an agent via Apify's MCP server, with a stable, documented schema, so an agent can watch a vendor list and act on changes without knowing anything about page markup.
Can I export to CSV or Excel? Yes. The dataset exports as CSV, Excel, JSON, NDJSON, or XML.
Is this legal? These are public pages that vendors publish specifically to disclose their subprocessors. The monitor reads them as published, on a polite schedule. It does not log in, bypass access controls, or touch anything non-public.