Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>Ziplore: free US ZIP code lookup & radius search</title> | |
| <meta name="description" content="Free US ZIP code lookup: city, county, time zone, population, income and home value for any ZIP, plus every ZIP within N miles."> | |
| <style> | |
| :root { --bg: #fbfaf7; --fg: #1d2330; --muted: #5d6675; --line: #e3e0d8; --card: #fff; --accent: #1f6f5c; --accent-fg: #fff; } | |
| @media (prefers-color-scheme: dark) { :root { --bg: #14171c; --fg: #e8e6e1; --muted: #9aa3ad; --line: #2b3038; --card: #1b1f26; --accent: #4fb89b; --accent-fg: #0d1a16; } } | |
| * { box-sizing: border-box; } | |
| body { margin: 0; background: var(--bg); color: var(--fg); font: 16px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif; } | |
| main { max-width: 980px; margin: 0 auto; padding: 24px 16px 48px; } | |
| h1 { font-size: 1.7rem; margin: 0 0 4px; } | |
| .sub { color: var(--muted); margin: 0 0 20px; } | |
| form { display: flex; flex-wrap: wrap; gap: 8px; align-items: end; background: var(--card); border: 1px solid var(--line); border-radius: 10px; padding: 14px; } | |
| label { display: flex; flex-direction: column; font-size: .85rem; color: var(--muted); gap: 4px; } | |
| input { font: inherit; padding: 8px 10px; border: 1px solid var(--line); border-radius: 6px; background: var(--bg); color: var(--fg); width: 150px; } | |
| button { font: inherit; padding: 9px 16px; border: 0; border-radius: 6px; background: var(--accent); color: var(--accent-fg); cursor: pointer; } | |
| #status { color: var(--muted); margin: 12px 0; min-height: 1.5em; } | |
| .wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: 10px; background: var(--card); } | |
| table { border-collapse: collapse; width: 100%; font-size: .9rem; } | |
| th, td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--line); white-space: nowrap; } | |
| th { font-weight: 600; color: var(--muted); } | |
| td.n { text-align: right; font-variant-numeric: tabular-nums; } | |
| .cta { margin-top: 24px; padding: 16px; border-radius: 10px; border: 1px solid var(--accent); background: var(--card); } | |
| .cta a { color: var(--accent); font-weight: 600; } | |
| footer { margin-top: 28px; color: var(--muted); font-size: .8rem; } | |
| footer a { color: inherit; } | |
| </style> | |
| <!-- cm:studio-meta --><meta property="og:image" content="https://cybermax-tools-cybermax.static.hf.space/brand/zip-data-api/cover.png"><meta property="og:image:width" content="1200"><meta property="og:image:height" content="630"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://cybermax-tools-cybermax.static.hf.space/brand/zip-data-api/cover.png"><link rel="icon" type="image/png" href="https://cybermax-tools-cybermax.static.hf.space/brand/zip-data-api/icon.png"><!-- /cm:studio-meta --> | |
| </head> | |
| <body><!-- cybermax-bridge:start --><div style="max-width:960px;margin:8px auto;padding:8px 14px;border:1px solid rgba(127,127,127,.35);border-radius:10px;font:14px/1.5 system-ui,sans-serif"><b>Need it fresh, filtered or via API?</b> This demo shows a free snapshot, last updated 2026-09-27. <a href="https://data.cybermax-tools.workers.dev/buy/ziplore-api?s=sp-us-zip-codes-demographics" target="_blank" rel="noopener" style="color:inherit;font-weight:600">Ziplore ZIP code API</a> (200 free calls a day, then $19/month for 60,000) · <a href="https://data.cybermax-tools.workers.dev/buy/coffermap?s=sp-us-zip-codes-demographics" target="_blank" rel="noopener" style="color:inherit;font-weight:600">Coffermap FY2025 federal spending workbook</a> ($15) · <a href="https://data.cybermax-tools.workers.dev/notify?ds=us-zip-codes-demographics&s=sp-us-zip-codes-demographics" target="_blank" rel="noopener" style="color:inherit">email me when the data updates</a></div><!-- cybermax-bridge:end --> | |
| <main> | |
| <h1>Ziplore: free US ZIP code lookup & radius search</h1> | |
| <p class="sub">City, county, time zone and Census demographics for any US ZIP code, and every ZIP within a radius. 41,682 ZIPs, all in your browser.</p> | |
| <form id="f"> | |
| <label>ZIP code or "lat,lon" <input id="q" value="10001" autocomplete="postal-code"></label> | |
| <label>Radius (miles, 0 = just this ZIP) <input id="mi" type="number" min="0" max="100" step="1" value="2"></label> | |
| <label>Min. population <input id="minpop" type="number" min="0" step="100" value="0"></label> | |
| <button type="submit">Look up</button> | |
| </form> | |
| <div id="status">Loading ZIP table…</div> | |
| <div class="wrap"><table id="t"><thead><tr><th>ZIP</th><th>City</th><th>State</th><th>County</th><th>Miles</th><th>Time zone</th><th>Local time</th><th>Population</th><th>Median household income</th><th>Median home value</th><th>Median rent</th><th>Median age</th></tr></thead><tbody></tbody></table></div> | |
| <div class="cta"> | |
| <strong>Need this for a whole list, inside a workflow, or for an AI agent?</strong> | |
| <a href="https://apify.com/cybermax/zip-data-api" target="_blank" rel="noopener">Run Ziplore on Apify</a>: send thousands of ZIPs, addresses, "City, ST" names or coordinates and get clean JSON with county FIPS, every county a ZIP touches, UTC offsets, per-capita income, owner-occupied share and nearby ZIPs. $0.0005 per ZIP, unknown ZIPs free, and it works as an MCP tool for Claude and Cursor. | |
| Bulk data: <a href="https://huggingface.co/datasets/CyberMax-tools/us-zip-codes-demographics" target="_blank" rel="noopener">free dataset (CSV)</a>. | |
| </div> | |
| <footer> | |
| Data: <a href="https://www.geonames.org/">GeoNames</a> (CC BY 4.0), US Census Bureau (2024 Gazetteer, ACS 2020–2024 5-year estimates), time zones from timezone-boundary-builder (ODbL, © OpenStreetMap contributors). Distances are between ZIP center points. Home values of $2,000,000 and incomes of $250,000 are Census caps ("or more"). Made by CyberMax. Not affiliated with USPS or the Census Bureau. | |
| </footer> | |
| </main> | |
| <script> | |
| let rows = [], byZip = new Map(); | |
| const $ = (id) => document.getElementById(id); | |
| const fmt = (v, pre = '') => v == null ? '–' : pre + Number(v).toLocaleString('en-US'); | |
| const esc = (s) => String(s ?? '').replace(/[&<>"]/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"' }[c])); | |
| function miles(a, b, c, d) { | |
| const r = Math.PI / 180, x = Math.sin((c - a) * r / 2) ** 2 + Math.cos(a * r) * Math.cos(c * r) * Math.sin((d - b) * r / 2) ** 2; | |
| return 2 * 3958.7613 * Math.asin(Math.min(1, Math.sqrt(x))); | |
| } | |
| function localTime(tz) { | |
| if (!tz) return '–'; | |
| try { return new Intl.DateTimeFormat('en-US', { timeZone: tz, hour: 'numeric', minute: '2-digit' }).format(new Date()); } catch { return '–'; } | |
| } | |
| function render(list) { | |
| $('t').tBodies[0].innerHTML = list.map(([d, r]) => `<tr><td>${esc(r.zip)}</td><td>${esc(r.city)}</td><td>${esc(r.state)}</td><td>${esc(r.county)}</td> | |
| <td class="n">${d == null ? '–' : d.toFixed(1)}</td><td>${esc(r.timezone || '–')}</td><td>${localTime(r.timezone)}</td><td class="n">${fmt(r.population)}</td> | |
| <td class="n">${fmt(r.medianHouseholdIncome, '$')}</td><td class="n">${fmt(r.medianHomeValue, '$')}</td><td class="n">${fmt(r.medianGrossRent, '$')}</td><td class="n">${r.medianAge ?? '–'}</td></tr>`).join(''); | |
| } | |
| function run() { | |
| const q = $('q').value.trim(), mi = Math.min(Math.max(Number($('mi').value) || 0, 0), 100), minPop = Number($('minpop').value) || 0; | |
| let lat, lon, center; | |
| const pt = q.match(/^(-?\d+(?:\.\d+)?)\s*[,\s]\s*(-?\d+(?:\.\d+)?)$/); | |
| if (pt) { lat = +pt[1]; lon = +pt[2]; } | |
| else { | |
| const z = (q.match(/\d{5}/) || [q.replace(/\D/g, '').padStart(5, '0')])[0]; | |
| center = byZip.get(z); | |
| if (!center) { $('status').textContent = `${z} isn't a US ZIP code in this table.`; render([]); return; } | |
| lat = center.latitude; lon = center.longitude; | |
| } | |
| let list; | |
| if (mi > 0 || !center) { | |
| list = rows.filter((r) => !['AA', 'AE', 'AP'].includes(r.state)).map((r) => [miles(lat, lon, r.latitude, r.longitude), r]); | |
| list = mi > 0 ? list.filter(([d]) => d <= mi) : [list.filter(([, r]) => r.hasZcta).sort((a, b) => a[0] - b[0])[0]].filter(Boolean); | |
| list = list.filter(([d, r]) => (r.population ?? 0) >= minPop || (center && r === center)).sort((a, b) => a[0] - b[0]); | |
| } else list = [[null, center]]; | |
| const shown = list.slice(0, 300); | |
| $('status').textContent = mi > 0 ? `${list.length} ZIP code${list.length === 1 ? '' : 's'} within ${mi} miles${list.length > 300 ? ' (first 300 shown)' : ''}.` : (center ? '' : 'Nearest ZIP code to that point:'); | |
| render(shown); | |
| } | |
| $('f').addEventListener('submit', (e) => { e.preventDefault(); run(); }); | |
| fetch('zips.json').then((r) => r.json()).then(({ cols, rows: raw }) => { | |
| rows = raw.map((a) => Object.fromEntries(cols.map((c, i) => [c, a[i]]))); | |
| byZip = new Map(rows.map((r) => [r.zip, r])); | |
| $('status').textContent = ''; | |
| run(); | |
| }).catch(() => { $('status').textContent = 'Could not load the ZIP table. Reload the page.'; }); | |
| </script> | |
| <!-- cybermax-more:start --><div style="max-width:960px;margin:24px auto 32px;padding:12px 0;border-top:1px solid rgba(127,127,127,.3);font-size:14px;line-height:1.6"><b>Coming soon:</b> the Ziplore API (look up any ZIP code, radius search and demographics via API) is launching on the Apify Store; see <a href="https://apify.com/cybermax" target="_blank" rel="noopener" style="color:inherit">CyberMax on Apify</a> for the live tools.<br><b>More free from CyberMax:</b> <a href="https://huggingface.co/spaces/CyberMax-tools/cybermax" target="_blank" rel="noopener" style="color:inherit">All free CyberMax demos & datasets</a> · <a href="https://huggingface.co/spaces/CyberMax-tools/batch-geocoder-demo" target="_blank" rel="noopener" style="color:inherit">Pinloft: Batch Geocoder with Census FIPS & Districts</a> · <a href="https://huggingface.co/spaces/CyberMax-tools/company-name-to-domain" target="_blank" rel="noopener" style="color:inherit">Namewhere: Company Name to Domain Finder</a> · <a href="https://huggingface.co/datasets/CyberMax-tools/us-zip-codes-demographics" target="_blank" rel="noopener" style="color:inherit">Ziplore US ZIP Codes with Census Demographics (41,682 ZIPs) (free dataset)</a> · <a href="https://huggingface.co/datasets/CyberMax-tools/fipsbook-us-census-geographies" target="_blank" rel="noopener" style="color:inherit">Fipsbook: US Census Geographies with FIPS Codes, Centroids & Land Area (2025) (free dataset)</a></div><!-- cybermax-more:end --> | |
| <!-- cybermax-count:start --><script>(function(){try{var u="https://data.cybermax-tools.workers.dev/v?p="+encodeURIComponent(location.host+location.pathname)+"&r="+encodeURIComponent((document.referrer||"").split("/")[2]||"")+(function(){var q=new URLSearchParams(location.search),s=q.get("utm_source");return s?"&us="+encodeURIComponent(s)+"&uc="+encodeURIComponent(q.get("utm_campaign")||""):""})();navigator.sendBeacon?navigator.sendBeacon(u):(new Image).src=u}catch(e){}})()</script><!-- cybermax-count:end --></body> | |
| </html> | |