Why a captured site looks broken until you stop opening it as a file
September 23, 2026
We ran a full capture against a real Webflow portfolio site built on GSAP,
ScrollTrigger, Lenis and Three.js — the kind of heavily-animated site
Enrichr exists for. The extraction itself was thorough: 200 design tokens,
thousands of scripted animations accounted for, sixteen 3D meshes exported,
five source maps recovered down to original pre-minified files. Then we did
the obvious next thing: unzipped the capture and double-clicked
index.html.
It rendered. And it was subtly wrong — a name that should have sat on one line overlapped itself, and a WebGL panel that should have shown a live preview was solid black.
The DOM was fine. The browser wasn't.
The layout, fonts, colours and copy were all correct — proof the capture itself was faithful. What was missing was anything the page's own JavaScript was supposed to do after load: position an intro animation, initialize a canvas. Opening devtools on the local file explained why:
Access to script at 'file:///.../assets/js/8e4f45dec0-20419.js'
from origin 'null' has been blocked by CORS policy: Cross origin
requests are only supported for protocol schemes: chrome,
chrome-untrusted, data, http, https.
Chrome refuses to load a <script type="module"> from a
file:// URL, full stop, by design — module scripts are
always fetched under the page's origin, and a local file has no origin to
fetch under. It isn't a bug and it isn't specific to this tool: it happens to
any static site you save to disk and open directly, the moment its
JavaScript ships as ES modules. That's an increasingly common default, not
an edge case.
With that script blocked, nothing downstream of it ran: GSAP never initialized, so elements sat in whatever pre-animation position their CSS put them in — which is what read as overlapping text. The WebGL canvas never got a rendering context, so it painted nothing.
Serving it over HTTP instead
We pointed a trivial static file server at the same unzipped folder and
loaded it over http://localhost instead of file://.
Console errors went from four to one — and the one remaining was an
analytics beacon correctly failing because it has nowhere real to report to,
not a capture defect. The module script loaded, GSAP ran, the name sat on one
line, and the layout matched the live site.
Nothing about the captured files changed between the two runs. Only the origin did.
What this means if you're using Enrichr
- If a downloaded capture opens with visual glitches — overlapping
elements, a blank canvas, animations that never fire — check the
console for a CORS error on a
type="module"script before assuming anything failed to capture. - Serving the folder locally (
npx serve, Python'shttp.server, or any static file server) resolves it completely, because the page then has a real origin to fetch modules under. - Static assets, plain
<script>tags, CSS and fonts are unaffected either way — this is specific to module scripts.
We're folding this into the product directly: a capture will be able to hand back a live preview link, served correctly, instead of asking you to work around a browser policy you shouldn't have to know about. Until then, the one-line fix above gets you the exact same result.