{"slug": "show-hn-perfectclone-yoink-the-source-code-of-any-website-not-an-ai-clone", "title": "Show HN: Perfectclone – Yoink the source code of any website, not an AI clone", "summary": "A developer released perfectclone, a Python 3.10+ command-line tool that mirrors a public website's own HTML, JavaScript, CSS, fonts and images via a Playwright browser crawl in about 15 seconds, producing a servable folder rather than an AI-regenerated lookalike. In the project's own compat.py comparison at 1440×900, perfectclone matched nine sites at 100% pixel accuracy with zero hydration errors — including huly.io, nextjs.org, astro.build, svelte.dev, vitepress.dev, docusaurus.io, wordpress.org/news, paulgraham.com and example.com — while framer.com scored 96% and webflow.com 93%, and every clone loaded with zero requests to trackers. The tool ships clone, serve, replace, rehost and strip-trackers commands, strips trackers by default, and is installable via pip or uvx.", "body_md": "**Pull the real frontend of any public site in ~15 seconds. No AI, no tokens.**\n\nperfectclone clones any website 1:1. It crawls the site with a real browser (Playwright), downloads the site's own HTML, JavaScript, CSS, fonts and images, and gives you a folder you can serve, edit and deploy. Then it lets you rebrand it, rehost it and strip the original owner's trackers without breaking it, including Next.js sites that hydrate on load.\n\n```\npip install perfectclone\n\nperfectclone clone example.com\nperfectclone serve example.com             # → http://localhost:8000\n```\n\nThat's it. Chromium is downloaded automatically the first time you clone. Requires Python 3.10+.\n\nOr try it without installing anything, using [uv](https://docs.astral.sh/uv/):\n\n```\nuvx perfectclone clone example.com\n```\n\nMost \"clone any website\" tools today regenerate the site: an AI agent looks at screenshots or scraped markup, writes a new React/Next.js app, and compares the result against the original with a visual-similarity score until it's close enough. That gets you a lookalike. The code is new, the behaviour is approximate, and there are always gaps.\n\nperfectclone doesn't regenerate anything. It mirrors the bytes the site actually serves, so\nthe clone *is* the site: same markup, same bundles, same animations, same JavaScript running.\nSometimes the real solution is the simple one.\n\n|  | AI cloners | wget / HTTrack | perfectclone | \n|---|---|---|---|\n| Copies the site's real files | ❌ | ✅ | ✅ | \n| Pixel-identical on modern JS sites | ❌ | ❌ | ✅ | \n| Catches lazy-loaded JS, fonts, images | — | ❌ | ✅ | \n| React / Next.js sites still run | — | ❌ | ✅ | \n| Rebrand without breaking the site | ✅ |  | ✅ | \n| Strips the original site's trackers | — | ❌ | ✅ | \n| Works without an LLM or API key | ❌ | ✅ | ✅ | \n\nEach card is one site split down the middle: the live site on the left, the clone on the right.\n\n`scripts/compat.py` clones each site, serves the copy, and compares its home page with the live\none at 1440×900, with animations and videos paused on the same frame:\n\n| Site | Built with | Pixel match | Hydration errors | Notes | \n|---|---|---|---|---|\n| huly.io | Next.js | 100% | 0 |  | \n| nextjs.org | Next.js | 100% | 0 |  | \n| astro.build | Astro | 100% | 0 |  | \n| svelte.dev | SvelteKit | 100% | 0 |  | \n| vitepress.dev | VitePress (Vue) | 100% | 0 |  | \n| docusaurus.io | Docusaurus (React) | 100% | 0 |  | \n| wordpress.org/news | WordPress | 100% | 0 |  | \n| paulgraham.com | Hand-written HTML | 100% | 0 |  | \n| example.com | Static HTML | 100% | 0 |  | \n| framer.com | Framer | 96% | 0 | Cookie banner needs Framer's backend | \n| webflow.com | Webflow | 93% | 0 | Cookie banner won't run on localhost; carousel caught mid-scroll | \n\nEvery clone loaded with zero requests to trackers. Run it yourself with\n`python scripts/compat.py`, and please open an issue for any site that doesn't come out right.\n\n```\nperfectclone clone <url> [-o out] [--max-pages 200] [--extract] [--keep-trackers] [--ignore-robots]\nperfectclone serve <site> [-p 8000]\nperfectclone replace <site> <old> <new> [--exact-case] [--substring]\nperfectclone rehost <site> <old-origin> <new-origin>\nperfectclone strip-trackers <site>\n```\n\n- **clone** writes`out/site/` (the working copy) and`out/manifest.json` (pages, failures,\nthird-party hosts the site uses).`--extract` also saves each page's text, metadata\n(headings, links, images, forms, JSON-LD) and a full-page screenshot to`out/extract/` .\nTrackers are stripped by default.\n- **replace** renames text everywhere: HTML, JS, CSS, JSON, SVG. It also handles the UPPER,\nlower and Capitalized variants, and leaves URLs and asset paths alone so nothing 404s.\n- **rehost** points canonical, Open Graph, JSON-LD and sitemap URLs at your domain.\n- **serve** works like a static host: clean URLs (`/about` →`/about/index.html` ), and`/_next/image` requests are served from the mirrored originals.\n\nRebrand a clone and put it online:\n\n```\nperfectclone clone acme.com -o acme\nperfectclone replace acme \"Acme\" \"Globex\"\nperfectclone rehost  acme https://acme.com https://globex.com\nnpx netlify-cli deploy --dir acme/site --prod      # or any static host\n```\n\n1. **Crawl with a real browser.** Each page is rendered in Chromium and scrolled to the bottom,\nand every response is recorded. That catches what static mirrors miss: code-split JS chunks,\nfonts requested from CSS, images behind lazy loading. Links are followed breadth-first,\nseeded from the sitemap. robots.txt is respected unless you pass`--ignore-robots` .\n2. **Mirror the server's bytes.** Pages are saved as the HTML the*server* sends, not the\nrendered DOM, because that's what the site's JavaScript expects to hydrate. Assets keep\ntheir URL paths, and CSS/JS are scanned for further references (`url()` ,`srcset` , chunk\npaths) until nothing new turns up.\n3. **Edit without breaking hydration.** A Next.js App Router page ships its HTML*and* a\nserialized copy of the React tree in`self.__next_f.push(...)` script chunks. Change one and\nnot the other, and React throws a hydration error and re-renders from the payload, undoing\nyour edit. perfectclone decodes the payload stream, edits it row by row, recomputes the\nUTF-8 byte lengths of length-prefixed text rows (`<id>:T<hex>,…` ), rejoins rows that span\nchunks, and writes it back next to the matching HTML edit.\n4. **Strip trackers.** Google Analytics/Tag Manager, the Meta pixel, LinkedIn Insight, Hotjar,\nClarity, Segment, PostHog, HubSpot, TikTok, Reddit, X, Cloudflare Web Analytics, RB2B and\nmore. They're removed from`<script>` /`<noscript>` tags, from preload hints, and from Next.js`next/script` elements that only exist in the payload.\n\n- **No backend.** Forms, logins, search and API calls still go to the original servers (or\nfail). perfectclone copies the front end.\n- **Next.js client-side navigation** needs each page's RSC payload answered for`?_rsc=` requests. perfectclone mirrors them and`perfectclone serve` routes them. On a plain static\nhost, internal links fall back to full page loads: everything still works, just without the\ninstant transitions.\n- **Chunks that are only requested after a click** (say, a modal's code) are captured if the\ncrawl triggered them or a bundle names them as a string. A bundle can also assemble a chunk\nURL at runtime, and that one may be missed.\n- **Bot protection** (CAPTCHAs, aggressive Cloudflare rules) can block the crawl. perfectclone\ndoes not try to get around it.\n- Embeds (YouTube, Cal.com, maps) and third-party CDNs keep loading from their own hosts.\n\n**Clone apps behind a login, like dashboards.** Today perfectclone sees what an anonymous visitor\nsees, and data that loads from APIs after the page renders isn't kept. The plan, for apps you\nhave an account on:\n\n- **Crawl as you.** Sign in once in a browser window; perfectclone saves the session and\ncrawls with it.\n- **Record API responses.** Keep every JSON response the app fetches during the crawl and have`perfectclone serve` replay them, so charts, tables and lists show real data offline.\n- **Explore by clicking.** Click through navigation, tabs and menus to reach views that only\nexist in client-side routing.\n\nThe result is a clickable snapshot of the UI and its data at capture time. Saving, server-side filtering and live updates still need the real backend.\n\nOther ideas: hydration-aware editing for Nuxt, SvelteKit and Remix payloads, and a deploy\nhelper that writes `_redirects` / `vercel.json` rules so `?_rsc=` and `/_next/image` work on\nstatic hosts. Contributions welcome.\n\nperfectclone is open source under the [MIT License](https://github.com/eshaangulati123/perfectclone-website-cloner/blob/main/LICENSE). Issues and pull requests are\nwelcome, especially reports of sites that don't clone cleanly. See\n[CONTRIBUTING.md](https://github.com/eshaangulati123/perfectclone-website-cloner/blob/main/CONTRIBUTING.md), and please follow the [Code of Conduct](https://github.com/eshaangulati123/perfectclone-website-cloner/blob/main/CODE_OF_CONDUCT.md).\nReport security issues privately as described in [SECURITY.md](https://github.com/eshaangulati123/perfectclone-website-cloner/blob/main/SECURITY.md).", "url": "https://wpnews.pro/news/show-hn-perfectclone-yoink-the-source-code-of-any-website-not-an-ai-clone", "canonical_source": "https://github.com/eshaangulati123/perfectclone", "published_at": "2026-11-15 19:51:10+00:00", "updated_at": "2026-11-15 20:22:54.082651+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools"], "entities": ["perfectclone", "Playwright", "Next.js", "Astro", "SvelteKit", "VitePress", "Docusaurus", "Framer"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-perfectclone-yoink-the-source-code-of-any-website-not-an-ai-clone", "markdown": "https://wpnews.pro/news/show-hn-perfectclone-yoink-the-source-code-of-any-website-not-an-ai-clone.md", "text": "https://wpnews.pro/news/show-hn-perfectclone-yoink-the-source-code-of-any-website-not-an-ai-clone.txt", "jsonld": "https://wpnews.pro/news/show-hn-perfectclone-yoink-the-source-code-of-any-website-not-an-ai-clone.jsonld"}}