ScanRuns𝕏 Buy $REENG
reengineer Anything · docs

Take anything apart, from code.

reengineer Anything reads a public web page and writes down how it was built: framework, hosting, palette, fonts, page outline, scripts, API endpoints, storage keys and accessibility gaps. It hands everything back as one markdown file with a rebuild plan and a prompt you can paste into a coding agent.

You can use it three ways: the box on the home page, the HTTP API at /api/scan, or the reeng.js module, which you import straight from this site. No key, no account, no install.

NoteEvery scan is a real request to the target site made by our server. The scanner reads what the server sends. It does not log in, click around or run the page's JavaScript.

Quick start

One request gets you the whole plan. Pick your language:

curl -X POST https://reenganything.vercel.app/api/scan \
  -H 'Content-Type: application/json' \
  -d '{"url":"stripe.com","scope":"full","depth":"normal"}'
import { scan } from 'https://reenganything.vercel.app/lib/reeng.js';

const run = await scan('stripe.com');
console.log(run.stack);     // ['Next.js', 'React', 'Sentry', ...]
console.log(run.markdown);  // the full reconstruction plan
import requests

r = requests.post('https://reenganything.vercel.app/api/scan',
                  json={'url': 'stripe.com', 'scope': 'full'}).json()
open(f"reconstruction-{r['domain']}.md", 'w').write(r['markdown'])

The answer comes back in one response, usually in 1 to 5 seconds. There is no run ID and nothing to poll.

How it works

Each scan runs the same pipeline. The steps array in the response is the real log of it, with milliseconds since start.

  1. Resolve. The host is looked up in DNS. Private, loopback, link-local and internal addresses are refused before any request is made.
  2. Fetch. The page is requested with a normal browser user agent. Redirects are followed by hand, up to 5, and every hop is checked again.
  3. Parse. The HTML is walked for elements, nesting depth, headings, landmarks, links, forms, media and class names.
  4. Read styles. Linked stylesheets are fetched (how many depends on depth) and mined for colors, CSS variables, font families, @font-face, breakpoints, radii and motion.
  5. Read bundles. First-party scripts are fetched and searched for API paths, sockets, storage keys and library fingerprints.
  6. Match. Around 90 signatures are tested against HTML, CSS, JS and response headers. Every hit keeps its evidence.
  7. Write. Findings become markdown, filtered by scope, ending with a rebuild plan and an agent prompt.

Scope

Scope decides which sections land in the markdown. The scan itself is the same; you just get less to read.

ValueLabel on the siteSections
fullEverythingAll of them, plus the rebuild plan and agent prompt
apiJust the APIStack, scripts + deps, API surface, storage, hosting + headers
uiUI + design stuffStack, design system, structure, accessibility, assets, rebuild plan
bundleBundles onlyStack, scripts + deps, API surface, storage

Depth

Depth decides how much the scanner downloads besides the page itself.

ValueStylesheetsFirst-party bundlesrobots + sitemapTime budget
quick0 (inline only)0no9 s
normalup to 4up to 3yes16 s
deepup to 10up to 8yes26 s
NoteEach extra file is capped at 2 MB for CSS and 3.5 MB for JS. Anything larger is read up to the cap and marked truncated in the log.

Output format

The markdown always opens with a # Reconstruction: <domain> title and a quoted line with the time, scope, depth and duration. Then come these ## sections, in this order:

SectionWhat is inside
TL;DROne paragraph summary and a table with title, description, final URL, HTTP status, size, language
StackLayer, name and the exact evidence string for every signature hit, plus JSON-LD types
Design systemPalette by frequency with a role guess, color tokens as a :root block, type, breakpoints, radii, motion
StructureElement counts, top tags, custom elements, nav items, heading outline, internal routes, outbound domains, forms
Scripts + depsExternal and inline scripts, loading strategy, third-party hosts, bundles read with sizes
API surfaceEndpoints found in HTML and bundles, marked path, url or socket; fetch and XHR counts
StoragelocalStorage and sessionStorage keys, IndexedDB names, cookies, Cache API, service worker
Accessibilitylang, landmarks, h1 count, heading skips, images without alt, unlabeled inputs, aria, tabindex, skip link
AssetsImages by format, lazy and srcset counts, inline SVG, video, canvas, iframes, favicon, share image
Hosting + headersUseful response headers, a security header checklist, robots.txt and sitemap.xml
Rebuild planSuggested stack, a token block to paste, pages, sections in order, endpoints to stub, services to swap
Prompt for your agentA plain-text brief for Claude Code, Cursor or any agent to rebuild the page with your own copy

Section names are stable, so you can split the file by ## headings. sections() in reeng.js does exactly that.

Signatures

A signature is a pattern with a name and a layer. A hit is only reported with the evidence that triggered it, so you can check it yourself.

LayerExamples
FrameworkNext.js, Nuxt, Remix, Astro, SvelteKit, Gatsby, Angular
UI libraryReact, Vue, Svelte, Preact, Alpine.js, htmx, jQuery
CMS / builderWordPress, Shopify, Ghost, Webflow, Framer, Wix, Squarespace
CSSTailwind CSS (by utility class count), Bootstrap, Bulma, styled-components, Emotion, CSS modules
Fonts, icons, motionGoogle Fonts, Adobe Fonts, Font Awesome, Lucide, GSAP, Framer Motion, Lottie, Lenis
3D / canvasThree.js, Spline, PixiJS
AnalyticsGoogle Analytics, GTM, Plausible, PostHog, Segment, Mixpanel, Amplitude, Hotjar, Clarity, Meta Pixel
ServicesSentry, Datadog, Stripe, Paddle, Intercom, Crisp, HubSpot, reCAPTCHA, Turnstile
Backend / authFirebase, Supabase, GraphQL, Auth0, Clerk
Web3Solana web3.js, Phantom, wagmi / viem, ethers.js
Hosting / CDNVercel, Netlify, Cloudflare, CloudFront, S3, Firebase Hosting, GitHub Pages, Fly.io, Render, Fastly, Akamai
WarningSignatures can give false positives when a site merely mentions a tool in its text, for example a customer logo wall. The evidence column is there so you can tell.

POST /api/scan

POST/api/scan
GET/api/scan?url=stripe.com&scope=full&depth=normal

Both forms do the same thing. GET is handy for quick checks in a browser tab. CORS is open, so you can call it from any page.

FieldTypeDefaultNotes
urlstringrequiredWith or without https://. Paths are fine: vercel.com/pricing
scopestringfullfull · api · ui · bundle
depthstringnormalquick · normal · deep

Response

200 · application/json
{
  "status": "complete",
  "domain": "linear.app",
  "url": "https://linear.app/",
  "scope": "full",
  "depth": "normal",
  "elapsed": "1.3",
  "stats": [
    { "label": "nodes", "value": 4781 },
    { "label": "scripts", "value": 16 },
    { "label": "stylesheets", "value": 47 },
    { "label": "colors", "value": 14 },
    { "label": "endpoints", "value": 8 },
    { "label": "tech", "value": 6 }
  ],
  "steps": [{ "t": 0, "s": "resolving linear.app" }, "..."],
  "stack": ["Next.js", "React", "Tailwind CSS", "styled-components", "Cloudflare"],
  "palette": ["#9c9da1", "#000000", "#ffffff", "#626366", "#191d20"],
  "markdown": "# Reconstruction: linear.app\n...",
  "version": "1.0.0",
  "scannedAt": "2026-11-04T15:15:00.000Z"
}

If the same URL, scope and depth were scanned in the last 10 minutes, you get the stored result with "cached": true, and it does not count against your limit.

Errors + limits

Errors come back as {"status":"error","error":"..."} with a matching HTTP code. The message is written for humans, so you can show it as is.

CodeWhen
400Missing or malformed URL, a non-http scheme, a custom port or credentials in the URL
403The host resolves to a private, loopback or internal address
415The URL serves something that is not a page, like a PDF or an image
422DNS lookup failed. Usually a typo in the domain
429Rate limited. retryAfter in the body and the Retry-After header say how many seconds to wait
504The site did not answer in time or dropped the connection
508More than 5 redirects
LimitValue
Per IP, short window6 scans per 10 minutes
Per IP, long window20 scans per hour
Page size read4 MB of HTML
Cache10 minutes per URL + scope + depth

reeng.js

A 3 KB ES module that lives on this site at /lib/reeng.js. Import it by URL. It works in browsers, Deno, Bun and Node 18 or newer.

js
import { scan, sections, tokens, prompt, download } from 'https://reenganything.vercel.app/lib/reeng.js';

const run = await scan('vercel.com/pricing', { scope: 'ui', depth: 'deep' });

sections(run.markdown)['Stack'];  // that section as a string
tokens(run.markdown);             // ':root { --bg: ...; --ink: ...; }'
prompt(run.markdown);             // the agent brief, ready to paste
download(run);                    // browser only: saves reconstruction-vercel.com.md
ExportWhat it does
scan(url, opts)Calls the API. opts: scope, depth, signal, endpoint. Throws ScanError with status and retryAfter
scanPolitely(url, opts, tries)Same, but waits and retries on 429 up to tries times
sections(md)Splits the markdown into an object keyed by ## heading
tokens(md)Returns the :root CSS block from the rebuild plan
prompt(md)Returns the agent prompt as plain text
download(run)Saves the markdown as a file in the browser

Try it

This box imports reeng.js from this site and calls scan(), then prints the tokens and the agent prompt.


      

For agents

The output is written to be read by a coding agent. A typical loop: scan the reference, save the file next to your project, and ask the agent to follow it.

sh
# save the plan, then hand it to your agent
curl -s "https://reenganything.vercel.app/api/scan?url=linear.app&scope=ui" \
  | python3 -c "import json,sys; print(json.load(sys.stdin)['markdown'])" > PLAN.md

claude "Read PLAN.md and rebuild that page in this folder with our own copy"

You can also give an agent the API as a tool. Describe it as: takes url, optional scope and depth; returns markdown.

Limits

  • No JavaScript runs. Pages that build everything in the browser show up as a thin shell. The TL;DR says so when it notices. Deep depth reads more bundles, which helps with endpoints and libraries, but not with the rendered DOM.
  • Public pages only. No cookies, no logins, no forms. If a page needs an account, the scan sees the login screen.
  • Bot walls. Some sites answer our server with 403 or 429. The log shows the status, and the markdown then describes the error page, not the site.
  • Colors are counted, not seen. The palette is ranked by how often a value appears in CSS, so a color used once in a giant hero may rank low.
  • Private networks are off limits. Addresses in 10/8, 172.16/12, 192.168/16, 127/8, 169.254/16, 100.64/10, IPv6 local ranges and names like .local or .internal are refused, including after redirects.
NoteUse what you learn to build your own thing. The agent prompt tells the agent to use your own copy and images, and it should.

$REENG

$REENG pays for the scanner. Creator fees cover the server time and agent credits that every scan burns, so the API stays free with no key.

FieldValue
Ticker$REENG
ChainSolana
Contractsoon

FAQ

Is it free?

Yes. No key and no account. The rate limits keep it free for everyone.

Why is my site shown as a shell with almost no elements?

It renders on the client. The server sends an empty root and JavaScript fills it in later. Try deep depth to read more bundles, or scan a page that is rendered on the server.

Can it scan a page behind a login?

No. It only reads what an anonymous visitor would get.

Do you keep my scans?

The server keeps a result for 10 minutes in memory so repeats are instant. The Yours tab on Runs lives in your own browser storage, and only you see it.

Why did a signature show up that the site does not use?

The pattern appeared somewhere in the HTML, CSS or bundles. Look at the evidence column in the Stack table to see what matched.

How is this different from viewing source?

View source gives you 4 MB of minified text. This gives you the twelve things you actually wanted, sorted and named, plus a plan.

reengineer Anything · scanner 1.0.0·Scan a site·Runs·Chart