The page an AI wrote works in the chat, and is blank when you open the file

The preview in the chat runs the page on a web server and hands it the libraries it imports. A double-clicked file gets neither. The first red line in the browser console says which one is missing, and each has a fix that takes a minute.

You asked Claude or ChatGPT for a page, a dashboard or a small app. It rendered perfectly in the preview. You downloaded it, double-clicked index.html, and got a white screen — or a page with the text but no chart, no buttons that do anything, no styling.

Nothing is wrong with your computer, and usually nothing is wrong with the code either. The preview runs the page on a web server and supplies the libraries the code asks for. A file opened from your disk gets neither: the browser treats it as coming from nowhere, refuses module scripts, fetch() calls and fonts from the same folder, and has no idea what import React from 'react' means. Open the browser console, read the first red line, and it tells you which of those you hit.

The 30-second version

Every message below was copied from the console of Chromium 153, opening a test page from disk on 6 November 2026. Chrome adds Uncaught in front of the ones that stop a script.

What the console says What it means Fix
Access to script at 'file:///…/main.js' from origin 'null' has been blocked by CORS policy A <script type="module" src="…"> tried to load a second file from disk Serve the folder instead of opening it
Fetch API cannot load file:///…/data.json. URL scheme "file" is not supported. The page reads its data with fetch() Serve the folder, or paste the data into the page
TypeError: Failed to resolve module specifier "react" The code imports a package by name, and nothing tells the browser where that package lives Add an import map, or build the project
SyntaxError: Unexpected token '<' The script contains JSX, which no browser runs as written Ask for plain JavaScript, or build the project
SyntaxError: Cannot use import statement outside a module An import sits in a script tag without type="module" Add type="module", then serve the folder
TypeError: Cannot read properties of undefined (reading 'get') Often: the code calls storage or an API that exists only inside the chat's preview Replace that call; see below
Failed to load resource: net::ERR_… on a CDN address The page pulls a library from the internet, and you are offline Reconnect, or download a plain <script src> library next to the page

What the preview has that the file doesn't

Three things, and every row above is one of them going missing.

A real address. A preview is a page served over https:// from somewhere. A double-clicked file is file:///Users/you/Downloads/app/index.html, and browsers no longer treat the folder around it as one site. MDN puts it plainly: many browsers, including Firefox and Chrome, now treat all local files as having opaque origins, so a local file whose requests need CORS — module scripts, fetch(), fonts — gets CORS errors. Firefox's change came out of a real vulnerability: a saved HTML file could read other files in its folder whose names it knew or guessed, and upload them somewhere. The demonstration was a malicious attachment, opened from an Android messaging app, reading other attachments the victim had received. It is not going back.

Packages, already installed. When code says import { LineChart } from 'recharts', something has to turn the word recharts into a file. In a preview, the chat service does that. In a bare HTML file, nothing does.

Features that live on the vendor's servers. Claude artifacts can store data between sessions, and some call Claude itself — in which case, Anthropic says, the app runs on Anthropic's infrastructure and its users sign in with a Claude account. Neither of those travels inside a downloaded .html file.

Open the console first

Before changing anything, look. Press F12 (or Cmd+Option+J in Chrome on a Mac, Cmd+Option+K in Firefox), choose the Console tab and reload the page. A double-clicked file on a Mac usually opens in Safari, which needs Settings → Advanced → "Show features for web developers" switched on first; then Cmd+Option+C opens its console. We did not test Safari; its messages, and possibly which requests it blocks, differ from the table above.

Read the first red line, not the last. A page that failed to load its main script will often print a second error a moment later about something that script was supposed to set up. The second one is a symptom.

The rest of this article goes through the errors in the order you are likely to see them.

The file:// wall: module scripts and fetch

The most common output from an AI coding tool is a small project — index.html, a main.js, maybe a style.css and a data.json — and the HTML loads the script with type="module".

That tag is the problem. Chrome blocks it from disk with:

TEXT
Access to script at 'file:///Users/you/Downloads/app/main.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.

The origin is 'null' because the file has no origin at all. Firefox says the same thing in its own words — the string in Firefox's source ends in (Reason: CORS request not http).

fetch() hits the same wall from a different side. A dashboard that loads data.json shows its frame and no numbers, with Fetch API cannot load file:///…/data.json. URL scheme "file" is not supported. The same applies to fonts loaded with @font-face from the same folder.

What does not hit it, measured on the same test pages: a module script written inline, inside the HTML, runs fine from disk as long as it imports nothing local; an ordinary <script src="https://…"> from a CDN loads; and a plain <script src="main.js">, a stylesheet and an image from the same folder all load too. The wall is about requests that need CORS — module scripts, fetch(), fonts — not about local files as such.

The fix is to serve the folder, which takes one command and is covered further down.

import React from 'react' has nowhere to go

This one appears whether or not you serve the folder, which is how you can tell it apart:

TEXT
TypeError: Failed to resolve module specifier "react". Relative references must start with either "/", "./", or "../".

Firefox puts it as: the specifier was a bare specifier, but was not remapped to anything.

A browser only understands imports that are addresses — ./chart.js, /lib/chart.js, https://…. A bare name like react needs a map. Add one in the <head>, above the first module script, pointing each name at a CDN copy:

HTML
<script type="importmap">
  {
    "imports": {
      "react": "https://esm.sh/react@18.3.1",
      "react-dom/client": "https://esm.sh/react-dom@18.3.1/client"
    }
  }
</script>

That is what an import map is for. It works even from a double-clicked file as long as the code that imports React is written inside the HTML, because the packages now come over https:// rather than from disk — an inline module with that map loaded React 18.3.1 from file:// in our test. If the code lives in a separate main.js, you still need to serve the folder. Pin the version, as above; an unpinned CDN address can change under you. Use the major version the code was written for — 18.3.1 is simply what we tested, and code written for React 19 may need 19.

It stops being worth it beyond two or three packages. At that point the AI almost certainly gave you, or can give you, a real project with a package.json — build that instead.

JSX the browser can't read

SyntaxError: Unexpected token '<' pointing at a line like return <div className="card"> means the file contains JSX. React code is usually written that way, and the preview compiles it before running it. A browser never does.

You have two honest options. Ask the model for the same page in plain JavaScript with no build step — it can do that, and for a single page it is often the better artifact anyway. Or ask for it as a Vite project, then run npm install and npm run dev and let the build tool do what the preview was doing for you.

Things only the chat can do

If the page loads but a button does nothing, and the console shows something like TypeError: Cannot read properties of undefined (reading 'get'), the code is calling a feature that exists only inside the chat — typically the artifact's own storage, or an artifact that sends prompts to Claude.

The storage is kept by Anthropic, per artifact, up to 20 MB of text. Your downloaded copy cannot reach it, so expect it to start empty. Ask the model to swap that storage for the browser's own localStorage, which works in a downloaded file — the data then lives in your browser instead.

An artifact that calls Claude is a different matter. Somebody has to authenticate and pay for those calls. Inside the chat, each user's own Claude account does both — Anthropic says usage counts against each person's own plan limits. Outside it, the page needs something in front of it that holds an API key — never the HTML itself.

Serve the folder instead of opening it

For everything in the file:// section, the fix is a local web server. If you have Python 3 — most Linux systems do, and on a Mac the first python3 may offer to install Apple's command line developer tools — open a terminal in the folder and run:

BASH
python3 -m http.server --bind 127.0.0.1

Then open http://127.0.0.1:8000/. On Windows the command starts with py -3 instead of python3, as MDN's local-server guide shows.

The --bind 127.0.0.1 part matters. Without it the server binds to all interfaces, which on a café or office network means anyone nearby can browse the folder you ran it in. Python's own documentation also says the module is not meant for production. Press Ctrl+C to stop it when you are done.

Now every file comes from the same origin, http://127.0.0.1:8000, and module scripts, fetch() and fonts all load.

When not to do this

Some fixes you will find elsewhere make things worse:

  • Do not start Chrome with --allow-file-access-from-files or with web security turned off to make a double-click work. Those switches remove the protection described above for every page you open in that browser, including ones you download later from people you do not know.
  • Do not hand-patch a real project with import maps. If there is a package.json, run npm install and the project's own dev command. Patching the output means patching it again every time the model revises the code.
  • Do not send the file to someone else and expect it to work. Unless the page is entirely self-contained, it will fail on their machine for exactly the same reasons, and they will not have this article open. If another person needs to see it, put it on a web address. That is what publishing what an AI made on dropto.run is for, and any static host will do the same job.

Questions

Why does it work in Claude or ChatGPT but not on my computer?

The preview serves the page from a web address and provides the libraries it imports. A file opened from disk has no address the browser trusts and no libraries beyond what is written in it.

Why does Firefox say "CORS request not http" about a file on my own disk?

Firefox and Chrome treat every local file as its own isolated origin, so a request from one local file for another that needs CORS — a module script, fetch(), a font — is refused, because CORS only works over HTTP or HTTPS. Plain scripts, stylesheets and images from the same folder still load.

Can I just delete type="module"?

Not if the code uses import. Without it, the browser stops at the first import with Cannot use import statement outside a module.

Is it safe to leave python3 -m http.server running?

With --bind 127.0.0.1, only your own machine can reach it. Without that flag it listens on every network interface. Either way, stop it when you are finished; it is a development tool, not a server to leave up.

Does the data I saved in the artifact come with the download?

No. Artifact storage is kept by Anthropic alongside the artifact, so a downloaded copy starts with nothing saved.

Why does it work at home and break on a plane?

The page loads a library or a font from a CDN. With no connection, that request fails and the page renders without it. Download the file next to the page and point the address at the local copy. That works from a double-click for a plain <script src>; a font or a module library saved locally also needs the folder served, for the reasons above.

Will it work if I email the HTML file to a client?

Only if everything it needs is inside that one file or loaded from a CDN — no separate .js, .css or data files beside it, no package imports, no JSX, no artifact storage. Otherwise they will see the same blank page you did. Send a link to a hosted copy instead.

This site is the product it is written about.

Drag a folder in and read the link back. No account and no card to publish.