Skip to content

Verifying It Works

Once Turbulence is set up for a domain, the easiest way to confirm it’s working is to load a page and check the response headers. There are a few different verification methods, ranging from a quick browser-level check to running the full pipeline on demand for a single URL. This page walks through each.

The fastest way to confirm Turbulence is in the path: open your site in a browser, open the browser’s Developer Tools, switch to the Network tab, and click on the top request (the HTML document itself). Then look at the response headers.

You should see headers like these:

X-PicPerf-Cache: HIT
X-PicPerf-Cache-Age: 142
X-PicPerf-Optimized: true
X-PicPerf-Steps: images,image-sizing,resource-hints,scripts,speculation-rules

What to look for:

  • X-PicPerf-Cache — this header is the clearest signal. If it’s there at all, your request went through Turbulence. HIT means the page was served from the edge cache, MISS means it was fetched from your origin and transformed just now (which happens on the first visit, then becomes HIT on subsequent visits), and STALE means it was served from cache but is being revalidated in the background.
  • X-PicPerf-Optimized — should be true. If it’s false, the pipeline ran but no transformation actually changed the HTML. This is rare and usually means the page is already well-optimized.
  • X-PicPerf-Steps — a comma-separated list of the transformations that modified the HTML. The exact set depends on your page, but seeing at least images and resource-hints is typical.

You can also confirm the same things from a terminal with curl:

Terminal window
curl -sI https://www.yourdomain.com/ | grep -i x-picperf

The -I flag fetches headers only, and the grep filters to the relevant ones. If you see any X-PicPerf-* headers in the output, you’re going through Turbulence.

Beyond the headers, you can look at the actual HTML being served. A few things to confirm:

Open the page source (right-click → “View Page Source” or use the Network tab’s “Response” view). Find an <img> tag. The src should look like:

<img src="https://picperf.io/t/width_1920/https://www.yourdomain.com/wp-content/uploads/2025/01/hero.jpg">

Images are rewritten in two steps: first to https://picperf.io/https://... (by the images step), then to https://picperf.io/t/width_N/https://... (by the image-sizing step). The exact width_N value depends on the image and the page, but the picperf.io prefix — with or without a /t/width_N/ segment — tells you the image is being routed through PicPerf’s optimization engine.

If you see <img src="https://www.yourdomain.com/..."> instead, with no picperf.io prefix, then one of these is happening:

  • The image is on a known CDN (Cloudinary, Imgix, etc.) and is being left alone on purpose.
  • The page is being served from a STALE cache entry that predates the image-routing step — try a hard refresh, or wait a few minutes for the cache to revalidate.

Scroll to the <head> of the document. You should see <link rel="preconnect"> and <link rel="dns-prefetch"> tags for the external origins your page depends on. For example:

<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preconnect" href="https://www.googletagmanager.com">
<link rel="dns-prefetch" href="https://cdn.example.com">

If you don’t see any resource hints, it might be that your page only references same-origin resources, in which case there’s nothing for Turbulence to preconnect to.

For Chromium-based browsers, look for a <script type="speculationrules"> block in the <head>:

<script type="speculationrules">
{
"prefetch": [{
"urls": ["/about", "/contact", "/blog"],
"eagerness": "moderate"
}]
}
</script>

The URLs in the list are same-origin links found on the page. If your page has no same-origin links (rare), the block will be missing — that’s expected.

If you use Google Fonts or Typekit (Adobe Fonts), the original <link rel="stylesheet" href="https://fonts.googleapis.com/..."> or <link rel="stylesheet" href="https://use.typekit.net/..."> should eventually be replaced with <!-- ⚡ INJECTED BY PICPERF ⚡ --> and an inline <style> block whose font URLs point at /pp-static/.... The first time you load a page, you may still see the original <link> — the fonts step runs in the background on the first visit. Reload once (or wait for cache revalidation) and you should see the self-hosted version. X-PicPerf-Steps should include fonts once the step has completed for that URL.

The ?pp_verify=1 query parameter forces Turbulence to skip the cache and run the full transformation pipeline inline (no two-stage split, no background work). The response you get is the fully-optimized HTML, and the headers are different:

Terminal window
curl -s "https://www.yourdomain.com/?pp_verify=1" | head -50

The response headers will include:

  • X-PicPerf-Cache: BYPASS — confirms the cache was skipped.
  • X-PicPerf-Verify: sync — confirms the synchronous pipeline ran.
  • X-PicPerf-Steps — the full list of steps that ran.

This is the most reliable way to confirm the pipeline is producing the output you expect, because nothing is being served from cache. Use it when you’re first setting up a domain, or whenever you want to be sure what visitors will see on a fresh request (not a cached one).

Note: this flag does not write the result back to the cache, so it doesn’t disturb what other visitors see. It’s a read-only check.

If you’d rather not poke around with headers, Turbulence’s free analysis tool does the verification for you. Enter any public URL and an email on the marketing site. The form submits to go.picperf.io/api/analyze/turbulence/proxy, which forwards the request to the optimization worker. A few minutes later you’ll receive an email with a link to a report at picperf.io/analyze/turbulence/{domain}/{key} showing:

  • The current PageSpeed Insights score (the “before”) — measured against the live URL.
  • The score after Turbulence’s transformations are applied (the “after”) — measured against the worker’s optimized preview of that page.
  • Lab metrics — LCP, FCP, TBT, CLS, and Speed Index — before and after.
  • A list of every transformation step that was applied.

This is also a good way to estimate the impact of Turbulence before pointing your real domain at it. The report simulates Turbulence’s optimizations on a single URL, so you can see the difference it would make on a representative page. Note: the form shows a success message immediately (optimistic UI) — if you don’t receive an email within a few minutes, check your spam folder or try again.

A few things to watch for as you verify:

  • X-PicPerf-Cache: MISS on every request. If you keep seeing MISS (not HIT) across multiple visits to the exact same URL, something is generating a different cache key each time. Common causes: tracking query parameters (?utm_source=, ?fbclid=, etc.) that change on every visit, or intentionally bypassing the cache with ?pp_verify=1 or ?bust=1 (dev only). There is no cache-purge button in the dashboard.
  • X-PicPerf-Steps is empty or missing. This means the pipeline ran but didn’t actually change the HTML. Common causes: the page doesn’t contain anything the pipeline rewrites (e.g., a single static text file with no images or scripts), or the page is being served from a STALE cache entry that predates the current step set. Try ?pp_verify=1 to force a fresh run.
  • A specific <img> isn’t going through PicPerf. Check the URL — if it’s on a known CDN (Cloudinary, Imgix, etc.), it’s being left alone on purpose. If it’s on your own origin and not being rewritten, it might be inside a <noscript> block, inside a JavaScript string, or in a CSS file Turbulence isn’t processing.
  • The HTML looks broken or has missing content. This is a bug. The most useful thing you can do is open a support ticket with the URL, a description of what’s missing, and a curl -s "https://your-url/?pp_verify=1" of what you’re seeing. Turbulence is designed to be transparent — your visitors should see exactly what they’d see from your origin, just with optimizations layered on top.

For more on diagnosing issues, see Troubleshooting.