# Third-Party Scripts Auditor (`phoenix2810/third-party-scripts-auditor`) Actor

Audit a public page for third-party scripts, stylesheets, and iframes. Classifies by known provider, flags render-blocking, missing SRI, non-HTTPS sources, and known trackers. Returns score, grade, and recommendations.

- **URL**: https://apify.com/phoenix2810/third-party-scripts-auditor.md
- **Developed by:** [Sanskar Jaiswal](https://apify.com/phoenix2810) (community)
- **Categories:** SEO tools, Developer tools, Open source
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Third-Party Scripts Auditor

Audit a public web page for third-party scripts, stylesheets, iframes, and other external resources in one API call. Returns per-resource classification by known provider, render-blocking flags, missing Subresource Integrity (SRI), non-HTTPS sources, known advertising and tracking scripts, a readiness score, letter grade, and recommendations. Built for performance engineers, security teams, privacy and compliance auditors, and site migration QA.

### Use cases

- **Performance engineers** - identify render-blocking scripts and stylesheets slowing first paint and Core Web Vitals
- **Security teams** - spot third-party scripts missing Subresource Integrity and loaded over insecure http://
- **Privacy and compliance auditors** - detect known advertising and tracking scripts for GDPR, CCPA, and consent reviews
- **Site migration QA** - verify that third-party dependencies survive CMS template changes, replatforming, and CDN cutovers
- **Frontend platform teams** - monitor which known providers (Google Analytics, Facebook Pixel, Stripe, HubSpot) load on key pages

### Input

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `startUrl` | string | yes | - | Public page URL to audit |
| `timeoutSeconds` | integer | no | `10` | Per-request timeout (3-30 seconds) |
| `maxHtmlBytes` | integer | no | `1048576` | Maximum HTML body size to download and parse (16 KB - 2 MB) |

#### Example input

```json
{
  "startUrl": "https://example.com",
  "timeoutSeconds": 10,
  "maxHtmlBytes": 1048576
}
```

### Output

A single dataset item with the full audit:

| Field | Type | Description |
|---|---|---|
| `inputUrl` | string | The URL provided as input |
| `finalUrl` | string | Final URL after redirects |
| `https` | boolean | Whether the final response was served over HTTPS |
| `resourceCount` | integer | Total number of resources found (scripts, stylesheets, iframes) |
| `firstPartyCount` | integer | Number of first-party external resources |
| `thirdPartyCount` | integer | Number of third-party external resources |
| `byType` | object | Count of resources grouped by tag type (script, link:stylesheet, link:preload, iframe) |
| `byProvider` | object | Count of third-party resources grouped by known provider name |
| `resources` | array | Per-resource analysis (see below) |
| `issues` | array | Aggregated issue descriptions across all resources |
| `score` | integer | Third-party scripts readiness score (0-100) |
| `grade` | string | Letter grade (A+, A, B, C, D, E, F) |
| `checkedAt` | string | ISO 8601 timestamp |
| `recommendations` | array | Actionable recommendations for improving third-party script posture |

#### `resources` array

Each entry contains:

| Field | Type | Description |
|---|---|---|
| `tag` | string | HTML tag type (script, link, iframe) |
| `rel` | string | null | The rel attribute for link tags (null otherwise) |
| `src` | string | The src or href attribute value (empty string for inline scripts) |
| `origin` | string | null | Resolved origin (protocol + host) of the resource, or null if unresolvable |
| `host` | string | null | Resolved hostname of the resource, or null if unresolvable |
| `provider` | string | Known provider name, "First-party", "Inline", or "Unknown" |
| `thirdParty` | boolean | Whether the resource loads from a different registrable domain than the page |
| `renderBlocking` | boolean | Whether the resource blocks HTML parsing or first paint |
| `hasSri` | boolean | Whether an integrity (SRI) attribute is present |
| `https` | boolean | null | Whether the resource uses HTTPS (null for inline or relative) |
| `tracker` | string | null | Known advertising/tracking provider name if detected, otherwise null |
| `module` | boolean | Whether a script uses type="module" |
| `issues` | array | Issue descriptions for this specific resource |
| `recommendation` | string | null | Fix recommendation for this resource (null when well-formed) |

#### Grading scale

| Score range | Grade |
|---|---|
| 95-100 | A+ |
| 85-94 | A |
| 75-84 | B |
| 65-74 | C |
| 50-64 | D |
| 30-49 | E |
| 0-29 | F |

Scoring starts at 100 when no resources are found, or 60 plus bonuses for no trackers, no render-blocking resources, no missing SRI, and no insecure sources. Penalties subtract for trackers, render-blocking scripts, missing SRI on third-party resources, insecure http:// sources, and total issue count.

#### Example output

```json
{
  "inputUrl": "https://example.com",
  "finalUrl": "https://example.com/",
  "https": true,
  "resourceCount": 3,
  "firstPartyCount": 1,
  "thirdPartyCount": 2,
  "byType": {
    "script": 3
  },
  "byProvider": {
    "Google Tag Manager": 1,
    "jsDelivr": 1
  },
  "resources": [
    {
      "tag": "script",
      "src": "https://www.googletagmanager.com/gtag/js?id=G-XXX",
      "origin": "https://www.googletagmanager.com",
      "host": "www.googletagmanager.com",
      "provider": "Google Tag Manager",
      "thirdParty": true,
      "renderBlocking": false,
      "hasSri": false,
      "https": true,
      "tracker": null,
      "module": false,
      "issues": ["missing Subresource Integrity (integrity attribute)"],
      "recommendation": "Add an integrity attribute (SRI hash) to third-party scripts to prevent CDN tampering."
    },
    {
      "tag": "script",
      "src": "https://cdn.jsdelivr.net/npm/lib@1.0.0/lib.min.js",
      "origin": "https://cdn.jsdelivr.net",
      "host": "cdn.jsdelivr.net",
      "provider": "jsDelivr",
      "thirdParty": true,
      "renderBlocking": false,
      "hasSri": true,
      "https": true,
      "tracker": null,
      "module": false,
      "issues": [],
      "recommendation": null
    },
    {
      "tag": "script",
      "src": "/app.js",
      "origin": "https://example.com",
      "host": "example.com",
      "provider": "First-party",
      "thirdParty": false,
      "renderBlocking": false,
      "hasSri": false,
      "https": "relative",
      "tracker": null,
      "module": false,
      "issues": [],
      "recommendation": null
    }
  ],
  "issues": [
    "script https://www.googletagmanager.com/gtag/js?id=G-XXX: missing Subresource Integrity (integrity attribute)"
  ],
  "score": 82,
  "grade": "B",
  "checkedAt": "2026-08-06T12:00:00.000Z",
  "recommendations": [
    "1 third-party script/stylesheet(s) missing Subresource Integrity. Add integrity hashes to protect against CDN tampering."
  ]
}
```

#### Known providers detected

The actor classifies resources from commonly seen providers, including: Google Analytics, Google Tag Manager, Google Fonts, Google Ads, YouTube, Facebook, Meta Pixel, X (Twitter), Hotjar, Microsoft Clarity, HubSpot, Stripe, Cloudflare, Bootstrap CDN, unpkg, jsDelivr, LinkedIn, TikTok, Pinterest, Amazon, Salesforce, Marketo, Zendesk, Intercom, Segment, Sentry, Datadog, Mixpanel, Amplitude, FullStory, Plausible, Matomo, and TikTok Pixel. Unknown third-party hosts are reported as "Unknown".

#### Known trackers flagged

The actor flags scripts from known advertising and tracking domains, including: Google Ads (DoubleClick, googleadservices, googlesyndication), Meta Pixel, TikTok Pixel, LinkedIn Insight, X (Twitter) Ads, Microsoft Ads (Bing), Criteo, Taboola, Outbrain, Yandex Metrica, and Baidu Ads.

#### Issues checked per resource

| Tag | Issue | Why it matters |
|---|---|---|
| script | render-blocking (no async/defer) | Blocks HTML parsing and slows first paint |
| script | missing Subresource Integrity | CDN tampering could inject malicious code |
| script | integrity requires crossorigin | SRI hash is ignored unless crossorigin is also set |
| script | insecure http:// source | Mixed-content warnings and MITM risk |
| link | render-blocking stylesheet | Blocks first paint until CSS downloads |
| link | missing Subresource Integrity | CDN tampering could inject malicious CSS |
| link | integrity requires crossorigin | SRI hash is ignored unless crossorigin is also set |
| link | insecure http:// stylesheet | Mixed-content warnings and MITM risk |
| iframe | missing loading="lazy" | Eager iframes defer layout and cost network |
| iframe | insecure http:// source | Mixed-content warnings and MITM risk |

### Security

- Only public HTTP/HTTPS URLs are accepted
- SSRF protection: localhost, private IPv4/IPv6, and DNS-resolving-to-private IPs are blocked
- URLs with embedded credentials are rejected
- Redirects are manually revalidated before following (max 3)
- HTML body is capped at `maxHtmlBytes` to prevent oversized responses
- No browser automation, no proxies, no cookies stored

### Pricing

Pay per event:

| Event | Price |
|---|---|
| Actor start | $0.005 |
| Page audited | $0.01 |

A single-page audit costs approximately $0.015.

### FAQ

**What is a third-party script?**
Any script, stylesheet, or iframe loaded from a different registrable domain than the page itself. The actor compares the last two labels of the hostnames (for example, `cdn.example.com` and `www.example.com` both count as first-party because they share the `example.com` suffix).

**How is this different from the HTTP Security Headers Auditor?**
The HTTP Security Headers Auditor inspects response headers like Content-Security-Policy, HSTS, and X-Frame-Options. This actor parses the HTML body to identify which third-party scripts, stylesheets, and iframes the page actually loads, classify them by provider, and flag per-resource issues such as render-blocking, missing SRI, and known trackers.

**How is this different from the Mixed Content Auditor?**
The Mixed Content Auditor looks for insecure `http://` subresources on an HTTPS page. This actor additionally classifies providers, flags render-blocking scripts and stylesheets, detects missing SRI, and identifies known advertising and tracking scripts.

**Does the actor execute the scripts or render the page?**
No. The actor fetches the HTML once, parses it with a lightweight scanner, and reports what it finds. It does not run JavaScript, so dynamically injected scripts are not detected. Use a browser-based actor for that.

**Can I audit multiple pages in one run?**
This actor audits one page per run. For bulk audits, schedule multiple runs.

**Does the actor follow redirects?**
Yes, up to 3 redirects. Each redirect target is revalidated for SSRF safety before it is followed.

# Actor input Schema

## `startUrl` (type: `string`):

Public page URL to audit. The actor fetches the HTML once and parses script, link, iframe, and img tags. HTTP and HTTPS only. Private IP ranges are blocked.

## `timeoutSeconds` (type: `integer`):

Timeout for the HTTP request.

## `maxHtmlBytes` (type: `integer`):

Maximum HTML body size to download and parse.

## Actor input object example

```json
{
  "startUrl": "https://example.com",
  "timeoutSeconds": 10,
  "maxHtmlBytes": 1048576
}
```

# Actor output Schema

## `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 = {
    "startUrl": "https://example.com"
};

// Run the Actor and wait for it to finish
const run = await client.actor("phoenix2810/third-party-scripts-auditor").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 = { "startUrl": "https://example.com" }

# Run the Actor and wait for it to finish
run = client.actor("phoenix2810/third-party-scripts-auditor").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 '{
  "startUrl": "https://example.com"
}' |
apify call phoenix2810/third-party-scripts-auditor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,phoenix2810/third-party-scripts-auditor"
        }
    }
}

```

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/zNaTNjSCZzmkRRmOT/builds/DGyd3XGi14fCGp9uy/openapi.json
