# Compression Headers Auditor (`phoenix2810/compression-headers-auditor`) Actor

Audit a public URL's HTTP compression headers for gzip, brotli, zstd, and deflate. Detects double-compression, re-compression of binary content, and missing Vary negotiation.

- **URL**: https://apify.com/phoenix2810/compression-headers-auditor.md
- **Developed by:** [Sanskar Jaiswal](https://apify.com/phoenix2810) (community)
- **Categories:** Developer tools, SEO 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

## Compression Headers Auditor

Audit a public URL's HTTP compression headers in one API call. Returns detection for `gzip`, `brotli`, `zstd`, and `deflate` in `Content-Encoding`, checks `Vary: Accept-Encoding` is present during negotiation, flags re-compression of already-compressed binary content (images, fonts, videos, archives), detects double-compression and legacy `Transfer-Encoding: gzip`, and returns a content-aware compressibility score, letter grade, and performance recommendations. Built for performance engineers, devops teams, and site migration QA.

### Use cases

- **Performance engineers** - verify brotli/gzip/zstd are correctly applied to text-based resources before launches and CDN cutovers
- **Devops teams** - catch compression regressions after edge config changes, origin moves, or CDN rule edits
- **Site migration QA** - confirm compression policies survive moves between frameworks, origins, and edge providers
- **Frontend platform teams** - detect wasted CPU from re-compressing already-compressed binary formats (JPEG, PNG, WOFF2, PDF, WASM)
- **Agency consultants** - batch-audit client pages and return structured compression recommendations

### Input

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `startUrl` | string | yes | - | Public URL to audit |
| `useHeadRequest` | boolean | no | `false` | Use HEAD instead of GET (some servers return different headers on HEAD) |
| `timeoutSeconds` | integer | no | `10` | Per-request timeout (3-30 seconds) |

#### Example input

```json
{
  "startUrl": "https://example.com",
  "useHeadRequest": false,
  "timeoutSeconds": 10
}
```

### 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 |
| `status` | integer | Final HTTP status code |
| `contentType` | string | Content-Type of the final response |
| `resourceClass` | string | Content class: `static-asset`, `html`, `already-compressed`, or `other` |
| `contentEncoding` | string | null | Parsed Content-Encoding value (e.g., `gzip`, `br`, `zstd`, `deflate`), or null if absent |
| `transferEncoding` | string | null | Parsed Transfer-Encoding value (e.g., `chunked`), or null if absent |
| `compressions` | array | Ordered list of detected compression algorithms in Content-Encoding |
| `varyAcceptEncoding` | boolean | Whether Vary includes Accept-Encoding |
| `vary` | array | Tokenized Vary header values |
| `contentLength` | integer | null | Content-Length response header value, or null |
| `headers` | array | Per-header analysis (see below) |
| `issues` | array | Aggregated issue descriptions |
| `score` | integer | Compression 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 compression |

#### `headers` array

Each entry contains:

| Field | Type | Description |
|---|---|---|
| `name` | string | Display name of the header check |
| `header` | string | Canonical header key |
| `status` | string | `good`, `warn`, `missing`, or `info` |
| `note` | string | Human-readable explanation of the current state |
| `weight` | integer | Weight of this check in the score |
| `recommendation` | string | null | Fix recommendation, or null when the header is good |

#### Headers checked

| Check | Header(s) | What is checked |
|---|---|---|
| Content-Encoding | `Content-Encoding` | presence, standard algorithm (gzip, br, zstd, deflate), double-compression, re-compression of already-compressed content types |
| Vary | `Vary` | whether `Accept-Encoding` is included when Content-Encoding is negotiated (prevents serving compressed responses to unsupported clients) |
| Compression Algorithm | `Content-Encoding` | algorithm quality assessment: brotli for text, zstd for modern compression, gzip for compatibility |
| Transfer-Encoding | `Transfer-Encoding` | flags legacy `Transfer-Encoding: gzip` (largely unsupported in HTTP/2+) |

#### Resource-aware scoring

The auditor classifies the response as `static-asset` (CSS, JS, JSON, XML, plain text), `html` (text/html, xhtml), `already-compressed` (images, fonts, videos, audio, archives, PDF, WASM), or `other`. Expectations differ:

- Text-based resources (HTML, CSS, JS, JSON) should use `Content-Encoding: gzip` or `br` (brotli preferred for ~15-25% better compression on text).
- Already-compressed content types (JPEG, PNG, WebP, WOFF2, MP4, ZIP, PDF, WASM) should NOT be re-compressed; doing so wastes CPU at the edge and rarely saves bytes.
- `Vary: Accept-Encoding` must be present whenever Content-Encoding is negotiated, so caches do not serve brotli/gzip to clients that only accept identity.

#### 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 |

#### Example output

```json
{
  "inputUrl": "https://example.com",
  "finalUrl": "https://example.com/",
  "https": true,
  "status": 200,
  "contentType": "text/html; charset=UTF-8",
  "resourceClass": "html",
  "contentEncoding": "gzip",
  "transferEncoding": null,
  "compressions": ["gzip"],
  "varyAcceptEncoding": true,
  "vary": ["accept-encoding"],
  "contentLength": 648,
  "headers": [
    {
      "name": "Content-Encoding",
      "header": "content-encoding",
      "status": "good",
      "note": "Content-Encoding: gzip. gzip (widely compatible).",
      "weight": 40,
      "recommendation": null
    },
    {
      "name": "Vary: Accept-Encoding",
      "header": "vary",
      "status": "good",
      "note": "Vary includes Accept-Encoding. Content negotiation for compression is correctly signalled.",
      "weight": 30,
      "recommendation": null
    }
  ],
  "issues": [],
  "score": 70,
  "grade": "C",
  "checkedAt": "2026-08-13T12:00:00.000Z",
  "recommendations": [
    "Compression headers look well-configured for this content type. Run this audit after edge/CDN changes to catch regressions."
  ]
}
```

### 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)
- No browser automation, no cookies stored, no body retained
- The actor drains the response body after reading headers (GET by default; HEAD optional)

### Pricing

Pay per event:

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

A single URL audit costs approximately $0.015.

### FAQ

**How is this different from the Cache Headers Auditor?**
The Cache Headers Auditor checks caching directives (`Cache-Control`, `ETag`, `Last-Modified`, `Expires`, `Vary`, `Age`). This actor focuses exclusively on compression: `Content-Encoding` algorithm choice, `Vary: Accept-Encoding` negotiation, re-compression of already-compressed content, double-compression, and `Transfer-Encoding` legacy issues.

**How is this different from the HTTP Compression Checker actor?**
The HTTP Compression Checker reports whether a URL serves brotli/gzip/deflate and whether Vary: Accept-Encoding is present. This actor adds: zstd support, already-compressed content-type detection (prevents wasted CPU re-compressing JPEG/PNG/WOFF2/PDF/WASM), double-compression detection, Transfer-Encoding legacy warnings, compression-choice quality scoring, content-aware compressibility scoring, and structured devops recommendations per resource class.

**Does the actor fetch the body?**
By default it issues a GET request and drains the body without parsing it. Use `useHeadRequest: true` to issue a HEAD instead; some servers return different headers on HEAD, so GET is safer by default.

**Can I audit static assets (CSS, JS, images, fonts)?**
Yes. The actor classifies the response using Content-Type and applies different expectations: text-based static assets should be compressed, but already-compressed content (images, fonts, videos, archives, PDF, WASM) should NOT be re-compressed.

**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 URL to audit. The actor fetches headers once and inspects compression-related response headers. HTTP and HTTPS only. Private IP ranges are blocked.

## `useHeadRequest` (type: `boolean`):

When true, the actor issues a HEAD request; some servers return different headers on HEAD. Defaults to false (GET, then drain body).

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

Timeout for the HTTP request.

## Actor input object example

```json
{
  "startUrl": "https://example.com",
  "useHeadRequest": false,
  "timeoutSeconds": 10
}
```

# 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/compression-headers-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/compression-headers-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/compression-headers-auditor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,phoenix2810/compression-headers-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/RMn2JPAvNuilc7VuL/builds/qv5s6AqwX3PIi6PCD/openapi.json
