Why fonts and logos break when you copy a website (and how to fix it)
The nine places a logo hides, the font race that silently reflows your copy, and how to check both survived before you rely on the file.
This is the single most common complaint about every page-copying tool, ours included — it is what most of our capture engineering has gone into. The causes are specific and fixable, and they are worth understanding whichever tool you use.
Why logos disappear
A "logo" is nine different things depending on how the site was built, and a naive copy only handles two of them.
<img src>— trivially copied.<img srcset>/<picture>— the copy may keep a different variant than the one you saw, or none.- Inline
<svg>— kept, but often unstyled: its size and colour usually come from a stylesheet, so it survives as a black or zero-height blob. <use href="#id">pointing at a hidden<symbol>sprite sheet — the single most common pattern in modern sites, and routinely dropped because the sprite lives in adisplay:nonecontainer that serialisers prune.- A CSS
background-imageon a::before— invisible to anything that only walks the DOM's attributes. - A CSS
mask-imageor-webkit-mask— same problem, plus the colour comes frombackground-color. - An icon font glyph — needs the font file, not the markup.
- A
<canvas>painting — has no URL at all; only pixels. - An
<object>or<iframe>embed.
Layer on top of that: even the ones that are referenced correctly break offline, because the asset was never carried. Hotlink protection returns 403 to a file:// referrer. Signed CDN URLs expire in hours. Image proxies refuse unknown referrers. So the copy looks perfect while you are online and next to the original — and it is empty a week later, which is when people notice.
The fix is not clever, it is thorough: resolve url() in stylesheets and in style attributes (where escaped quotes trip most parsers), keep hidden sprite sheets, carry the CSS that sizes and colours inline SVG, snapshot canvases as pixels, and embed the bytes of everything rather than the address. We built a fixture page containing all nine logo patterns, then render the copy with the origin killed: 2 of 9 survived before that work, 9 of 9 after.
Why fonts go wrong even when they are embedded
Two separate failures, and the second one is nastier.
The font never came. Webfonts are commonly served with CORS restrictions, from a different origin, or via a JavaScript loader that fires after a copy has been taken. Missing font, fallback face, different everything.
The font came and lost the race. This one cost us real fidelity points before we understood it. If a site declares font-display: optional, the browser is allowed to skip a webfont that is not ready almost immediately. On the original site the file is warm in cache and always wins. In a fresh copy the browser has to decode an embedded woff2 from a data URI, does not have it in the first few milliseconds, and renders the entire page in the fallback — permanently. Same bytes, different result: different glyph widths, different line breaks, a headline sitting 12px off.
The fix is to rewrite embedded faces to font-display: swap so the real face is always adopted once decoded. On one benchmark page that single change moved the score from 95.59% to 99.83%.
There is also a budget question. A page can declare thirty faces and render in four. Embedding all thirty makes an unusable file; the useful behaviour is to spend the budget on the faces the page actually renders in, which you only know by reading computed styles from the live DOM.
How to check your copy
- Open it offline. Block the original host or turn off the network. Everything that vanishes was a reference, not a copy.
- Watch the Network tab. Any request to the original domain is an asset you do not have.
- Inspect a heading → Computed →
font-family. A fallback here means every line in your copy wraps differently from the original. - Look for zero-size SVG. A missing sprite sheet usually shows as a 0×0 or square-black icon.
- Compare at 390px and 1440px. Mask and background-image failures often only show at one of them.
Our free font finder lists the faces a live page renders in, which is also the list you need for licensing before you publish anything built from a copy.
FAQ
Why are the fonts different in my saved webpage?
Either the font file was never embedded (CORS or a JS loader), or it was embedded but the page declared font-display: optional, in which case a fresh render keeps the fallback face permanently. Rewriting embedded faces to swap fixes the second case.
Why is the logo missing from my copy?
Most likely it lives in a hidden SVG sprite sheet, a CSS background, or a mask — three places a simple DOM copy does not look. It can also be present but unreachable: hotlink protection and signed CDN URLs both return nothing to an offline copy.
Can I legally use the fonts that came with a copied page?
Usually not. Webfont licences are tied to specific domains and traffic volumes, and re-hosting the file is a breach even if the design is yours. Identify the faces, then license or replace them.
Why do images look lower quality in the copy?
srcset and <picture> serve different files by viewport and pixel density. If the tool picked a different candidate than your screen did, you get a smaller or larger image than you saw. A capture that reads the rendered page knows which candidate was actually used.
How do I copy a page that uses an icon font?
The glyphs need the font file itself; copying the markup alone leaves empty boxes. Any copy that embeds the fonts a page renders in will carry icon fonts too.
Try it on the page you are looking at
CopyAnySite is a Chrome extension: open any page you can reach, press capture, and take away a standalone HTML file, an editable WordPress page, or a kit a coding agent can build from. The free key needs no card.
Download CopyAnySite