Skip to content

Downloaded Website Missing Images and CSS? How to Fix It

Downloaded website missing images and CSS? Match what you see to the cause (filters, CDNs, lazy loading, JavaScript, 403s, file:// paths) and fix it.

Website Downloader 10 min read

When a downloaded website is missing images and CSS, there are two broad causes. Either the files were never fetched, or they were fetched but the pages point to them with paths that break offline. Files go missing because of a filter, an asset on another domain or CDN, lazy loading, JavaScript rendering or a block from the server. Paths break because they are root-relative, still lead to the live site or are blocked under file://. Find your symptom below, then apply the fix for HTTrack, wget, WebCopy or a browser-based downloader.

Quick diagnosis: match what you see to the cause

Before you change any settings, open the downloaded folder and check whether the missing files are actually there. Then open the copy in your browser, press F12 and look at the Console and Network tabs. The failing URLs usually point straight at the cause.

What you seeMost likely causeSection
Plain text, blue links, no layout at allCSS never downloaded (filter, CDN, .tmp files) or root-relative paths under file://Files never downloaded / Files are there but broken
Layout works, but hero banners and section backgrounds are emptyImages referenced inside CSS filesCSS background images
Grey boxes, spinners or blurry thumbnails where photos should beLazy loading (data-src, srcset)Lazy-loaded images
Header and footer only, or a completely blank pageContent rendered by JavaScriptReact, Vue and Angular sites
Very few files, or error pages saved as content403 responses, rate limits, loginRefused downloads
Looks fine online, but clicking a link opens the live siteLinks were not rewrittenFiles are there but broken

One quick test: if the console shows file:///css/style.css (a path at the root of your drive), the file exists but is referenced with a root-relative path. If it shows https://cdn.something.com/..., the file was never saved because it lives on another host.

Why is my downloaded website missing images and CSS entirely?

If the folder contains HTML files and nothing else, or the css and images folders are empty, the crawler skipped those files. There are three usual reasons.

Filters and scan rules that exclude assets

A common cause of HTTrack not downloading images is a scan rule the user added, often copied from a forum post. Rules such as -* followed by +*.html keep only pages. HTTrack does not need a list of file types to grab images and stylesheets on the same site. What decides it is scope: files on the starting host are fetched, while files elsewhere are not. If you added filters, either remove them or allow assets explicitly:

+*.css +*.js +*.png +*.jpg +*.jpeg +*.gif +*.webp +*.svg +*.woff +*.woff2

Also start the crawl at the site root (https://example.com/), not at a subfolder such as /blog/. HTTrack's default travel mode stays below the starting directory, and wget's --no-parent does the same, so stylesheets in /assets/ or /wp-content/ can fall outside the crawl.

Why does HTTrack save .tmp files instead of CSS files?

The .tmp files are usually transfers that never finished, or files whose type HTTrack could not settle. This happens when the server sends a missing or wrong MIME type, or when the stylesheet is served from a script URL such as style.php?ver=6. To fix it, let the mirror run to completion and then use Continue interrupted download or Update existing download. If the problem is the MIME type, tell HTTrack what the file is with its --assume option, for example --assume php=text/css when PHP URLs return stylesheets. Use that only if they actually do.

Images and CSS on a CDN or another domain

Many sites serve their assets from a different host: cdn.example.com, an image service, Google Fonts or a theme's CDN. By default, crawlers do not leave the starting domain, so these files are missing from the copy even though every page downloaded. This is the usual explanation behind "website copied but no images".

  • HTTrack: enable Get non-HTML files related to a link (the -n / --near option), or add a rule such as +cdn.example.com/*.
  • wget: allow other hosts but name them, so the crawl does not wander across the web: wget --mirror --page-requisites --convert-links --adjust-extension --span-hosts --domains=example.com,cdn.example.com https://example.com/
  • WebCopy: add the asset domains to the crawl rules, or allow it to download resources from other hosts when they are linked from pages in scope.
With wget you have to list every asset host yourself. A browser-based downloader collects the stylesheets, scripts, images and fonts a page uses without any filter settings.

If you do not want to hunt down asset hosts and write filter rules, an online tool skips that step. Website Downloader fetches each subpage together with its images, stylesheets, scripts, fonts and media and delivers one ZIP file. The free plan covers up to 100 subpages, which is enough to check whether a problem site comes out complete. The trade-offs are compared in wget vs HTTrack vs an online website downloader.

Why are CSS background images missing from my offline copy?

Here the layout and fonts look right, but hero banners, section backgrounds and icons are blank. Those images are not referenced in the HTML. They live inside the stylesheet, in lines such as background-image: url(../img/hero.jpg).

Three things go wrong with them:

  1. The crawler never reads the CSS. A tool that parses only HTML does not see those references at all. Current wget versions parse url() in CSS files when you use --page-requisites. HTTrack also parses CSS, but it can miss URLs in @import chains, image-set() and inline style attributes.
  2. The relative path breaks. A url() inside a CSS file is resolved relative to the CSS file, not the page. If the tool saves the stylesheet in a different folder than the original, ../img/hero.jpg now points nowhere. Open the saved CSS, find one missing image and check whether that path exists next to it.
  3. The image is set by JavaScript. Sliders and parallax effects often set backgrounds through scripts, so neither the HTML nor the CSS contains the image URL.

To fix it, re-run with CSS parsing enabled and the asset host in scope. If only a handful of images are missing, download them by hand into the path the CSS expects.

Why are lazy-loaded images missing or blurry placeholders in the downloaded site?

Lazy loading sends a tiny placeholder first and swaps in the real photo when you scroll. The HTML looks something like <img src="placeholder.gif" data-src="photo.jpg">. A crawler follows src and saves the placeholder. data-src, data-lazy and similar attributes are invented by each plugin, so generic crawlers do not treat them as links.

  • Native lazy loading (loading="lazy") is harmless, because the real URL is still in src.
  • srcset lists several sizes of the same image. Older crawlers ignore it, so you get only the fallback image or a broken one at certain screen widths. Check your tool's documentation for srcset support.
  • Script-inserted galleries fetch their image lists from an API, and the URLs never appear in the page source.

Practical fixes: extract the URLs from the saved HTML (search for data-src=), put them in a text file and feed it to wget with wget -x -i urls.txt, which recreates the folder structure. Then replace data-src with src in the HTML with a search-and-replace. On a WordPress site you control, you can switch the lazy-load plugin off temporarily before you copy the site. For more on that route, see converting WordPress to static HTML.

Why does a React or Vue site download as an empty page?

Some sites send the browser an almost empty HTML file plus a large JavaScript bundle, and the bundle builds the page. Fully client-rendered React, Vue and Angular apps work this way. A crawler that does not run JavaScript saves only that shell: a <div id="root"></div>, perhaps a header, and no content. Cyotek's documentation is explicit that WebCopy does not execute JavaScript, and wget and HTTrack do not run it either. So the classic "WebCopy JavaScript site" complaint has no settings fix.

Website Downloader has the same limitation. A site that builds its content entirely in the browser can produce an archive with the page shell but not the content. Your realistic options:

  • If it is your site, export it from its source. Most frameworks have a static-site or pre-rendering mode that writes real HTML.
  • Check whether the site serves pre-rendered HTML. Many Next.js and Nuxt sites do, and those download normally. Use View source rather than the inspector: if the text appears in the raw source, a crawler can save it.
  • For a few pages, save the rendered page from your browser (Save page as, Complete). This captures the DOM as it appears at that moment, but the result often still depends on scripts.
Static files (HTML, CSS, JS, images, fonts, video, PDF) work offline. Anything that needs a server to respond, such as login pages, search, forms and APIs, does not, whichever tool made the copy.

Even when the content downloads, server-side features such as search boxes, contact forms, carts and comments stop working offline. That is expected and not a download error.

Why does the site return 403 or refuse the download?

If the copy contains a handful of files, error pages saved as index.html, or images replaced by "Access denied" responses, the server stopped the crawler. Typical reasons:

  • User-agent blocking. Some servers reject the default identifiers of wget and HTTrack. wget's --user-agent and HTTrack's -F change it.
  • Rate limits and bot protection. Too many requests per second trigger 403 or 429 responses. Slow down with --wait=1 --random-wait in wget, or fewer connections in HTTrack.
  • Hotlink protection. Images are refused when the request has no matching referrer.
  • Login. Pages behind a login return a login form instead of content.

Be careful here. A site that actively refuses automated access is signalling that it does not want to be copied, so check whether you have permission. For your own account, wget can reuse a browser session with --load-cookies. Website Downloader does not download pages behind a login. When a site refuses automated downloads, it reports the refusal instead of handing you an empty archive. If the site is already offline, a copy from the Internet Archive may be the better source: see restoring a website from the Wayback Machine.

Offline copy of website looks broken although the files are there

Everything is in the folder, yet the copy still shows no styling. This is a path problem, not a download problem.

Why does the copy look fine on a local server but broken when opened via file://?

When you double-click index.html, the browser opens it as file://. Three things behave differently there than on a web server:

  • Root-relative paths. /css/style.css means "from the root of the site" on a server, but "from the root of your drive" under file://. This is the most common reason a website gets downloaded without styling. The fix is to convert links to relative ones (css/style.css, ../css/style.css), which is what wget's --convert-links and HTTrack's default link rewriting do.
  • Browser security rules. Scripts loaded as ES modules, fetch() requests for JSON and sometimes web fonts are blocked from file:// pages.
  • A <base href> tag pointing to the live domain sends every relative link back online.

The quickest check is to serve the folder locally. Run python3 -m http.server 8000 inside it, then open http://localhost:8000. If the copy looks right there, the files are fine and only the paths need converting.

Why do links in the offline copy still go to the live site?

The links were never rewritten. Absolute URLs such as https://example.com/about/ stay absolute unless the tool converts them. With wget, add --convert-links (and --adjust-extension, so pages are saved with an .html extension). With HTTrack, check that you have not turned off its link rewriting. Remaining absolute links usually point to pages outside the crawl scope, which the tool correctly leaves alone.

A working offline copy has index.html and the subpage folders sitting next to css/, js/ and images/, with relative paths connecting them.

Website Downloader delivers this kind of structure as a single ZIP that opens offline in any browser. If you would rather not install anything, see the HTTrack alternative guide, or compare the plans on the pricing page if your site has more than 100 subpages.

FAQ

Which file types does HTTrack download by default?

HTTrack has no fixed list of file types. It saves whatever is linked from pages inside its scope, which means the same host and, by default, below the starting directory. Images, CSS and JavaScript on the same site are included without any rules. What gets left out is usually on another host or excluded by a scan rule you added.

Can I re-download only the missing assets instead of the whole site?

Yes. In HTTrack, use Update existing download after fixing your filters. It re-checks the mirror and fetches what is missing. With wget, re-run the same command with -N (timestamping) so unchanged files are skipped, or feed a list of missing URLs with -i urls.txt.

Does any tool fix a site that is built entirely with JavaScript?

Not reliably. Crawlers such as wget, HTTrack and WebCopy save the HTML the server sends, and for a client-rendered app that HTML is an empty shell. The dependable route is a static export from the site's source, or saving individual rendered pages from your browser.

When is an online downloader the simpler choice?

It is simpler when you do not want to write filter rules, list CDN domains or convert links by hand, or when you are on a Chromebook, tablet or work computer where you cannot install software. Website Downloader runs in the browser and delivers a ZIP. The free plan handles up to 100 subpages with no account. The FAQ covers the remaining details.

  • downloaded website missing images and CSS
  • troubleshooting
  • HTTrack
  • wget
  • offline websites