Free tool

Absolute Path Fixer

Paste a page, tell the tool how deep it sits in your folder tree, and every src, href, srcset and url() that starts with / is rewritten to a relative path that resolves inside an app. It also points out type="module" scripts and <base> tags while it is there.

Fix the paths

Text only, processed in your browser. Paste HTML or CSS.

Decides between css/x.css and ../css/x.css.

Absolute vs relative, in one paragraph

A path that starts with / is absolute: it is resolved from the root of the current origin. On https://example.com/pages/about.html, /css/style.css means https://example.com/css/style.css. A path without the leading slash is relative: it is resolved from the folder the current page is in, so from the same about.html, css/style.css means pages/css/style.css and ../css/style.css means css/style.css at the root. Inside a ZIP to APK app the pages are loaded from the app bundle, where "the root of the origin" is not your project, so absolute paths miss and relative paths hit.

Why the depth setting matters

The correct relative path depends on where the page lives. /css/style.css becomes css/style.css from index.html at the root, but ../css/style.css from pages/about.html. The tool cannot know where you copied the text from, so you tell it: root, one folder deep, two, or three. Run the tool once per depth — all the root pages together, then all the pages in pages/, and so on. A site with many pages at many depths is quicker to fix in your editor with a find-and-replace using the same rules, and the output here shows you exactly what those rules produce.

What it rewrites

Protocol-relative URLs (//cdn.example.com/…), full https:// URLs, anchors, mailto:, tel: and data: URIs are left alone.

What it deliberately does not do

It does not touch paths built in JavaScript (fetch('/api/data.json'), router.push('/about')), because rewriting code by pattern breaks more than it fixes; the tool lists module scripts so you know to look. It does not rewrite paths that are already relative, and it does not follow links to check the target exists — the ZIP Checker does that across the whole archive.

Better: fix it at the source

If the site comes from a static-site generator or a bundler, set the base path once and every build is correct. Vite: base: './'. Create React App: "homepage": "." in package.json. Next.js static export: assetPrefix: './' and hash-based navigation. Hugo: relativeURLs = true plus uglyURLs = true. Jekyll: {{ '/css/style.css' | relative_url }} with url left empty. The framework guide lists each setting.

Frequently asked questions

Will relative paths still work on my website?

Yes. Relative paths resolve identically on a web server and in an app, which is why they are the safe choice. Absolute paths only work on the web, and only when the site is served from the domain root.

Why does href="/" become index.html?

On a server, / is answered by a directory index — usually index.html — automatically. Inside an app there is no server to do that, so the link has to name the file. Untick the option if you handle the home link another way.

What about links like /about with no extension?

They become about (relative) but will still fail, because the file is about.html, not about. Extension-less URLs depend on a server rewrite. Rename the links to about.html, or configure your generator to emit .html links (Hugo's uglyURLs, for example).

Can it fix a whole folder at once?

Not in the browser — it works on pasted text. For a large site, use the rules it shows you in your editor's project-wide find-and-replace, or set your bundler's base path so the build emits relative paths in the first place.

Read next

Related tools

Ready to turn your ZIP into an APK?

Upload the ZIP of your HTML project, pick a name and an icon, and download a signed Android APK. Free, in the browser, no Android Studio.

Convert ZIP to APK