Spaces:
Paused
Paused
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <title>Ultra Powerful Scraper — Cloudflare Mode</title> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet"> | |
| <style> | |
| * { font-family: 'Inter', sans-serif; } | |
| body { | |
| background: | |
| radial-gradient(1200px at 15% 10%, #1e293b 0%, transparent 45%), | |
| radial-gradient(1200px at 85% 90%, #020617 0%, transparent 45%), | |
| linear-gradient(180deg, #020617, #020617); | |
| color: #fff; | |
| } | |
| .glass { | |
| background: rgba(15, 23, 42, 0.78); | |
| backdrop-filter: blur(22px); | |
| border: 1px solid rgba(148, 163, 184, 0.08); | |
| } | |
| .fade { | |
| animation: fade 0.6s ease forwards; | |
| } | |
| @keyframes fade { | |
| from { opacity: 0; transform: translateY(12px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .loader { | |
| width: 18px; | |
| height: 18px; | |
| border: 3px solid rgba(255,255,255,.25); | |
| border-top-color: white; | |
| border-radius: 50%; | |
| animation: spin .9s linear infinite; | |
| } | |
| @keyframes spin { to { transform: rotate(360deg); } } | |
| .badge { | |
| padding: 6px 14px; | |
| border-radius: 999px; | |
| font-size: 12px; | |
| font-weight: 600; | |
| } | |
| .scroll::-webkit-scrollbar { width: 6px; } | |
| .scroll::-webkit-scrollbar-thumb { | |
| background: #334155; | |
| border-radius: 999px; | |
| } | |
| </style> | |
| </head> | |
| <body class="min-h-screen p-6 flex justify-center items-center"> | |
| <div class="glass w-full max-w-6xl rounded-3xl shadow-2xl p-8 fade"> | |
| <!-- HEADER --> | |
| <div class="flex justify-between items-center mb-10"> | |
| <div> | |
| <h1 class="text-4xl font-extrabold">Ultra Powerful Scraper</h1> | |
| <p class="text-slate-400 mt-2"> | |
| Cloudflare Bypass · Stealth Browser · Industry Grade | |
| </p> | |
| </div> | |
| <div class="flex gap-3"> | |
| <span id="engineBadge" class="badge bg-slate-800 text-slate-400">ENGINE: IDLE</span> | |
| <span id="cfBadge" class="badge bg-slate-800 text-slate-400">CF: UNKNOWN</span> | |
| </div> | |
| </div> | |
| <!-- INPUT --> | |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6"> | |
| <div class="md:col-span-2"> | |
| <label class="text-sm text-slate-400">Target URL</label> | |
| <input id="urlInput" | |
| class="w-full mt-2 px-5 py-4 rounded-xl bg-slate-900 border border-slate-700 focus:ring-2 focus:ring-blue-600 outline-none" | |
| placeholder="https://example.com"> | |
| </div> | |
| <div class="flex items-end gap-4"> | |
| <button id="scrapeBtn" | |
| onclick="startScrape()" | |
| class="flex-1 py-4 rounded-xl bg-blue-600 hover:bg-blue-700 transition font-semibold flex items-center justify-center gap-3"> | |
| <span id="btnText">Start Scraping</span> | |
| <div id="btnLoader" class="loader hidden"></div> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- STATUS BAR --> | |
| <div class="flex flex-wrap gap-4 mb-8"> | |
| <span id="statusBadge" class="badge bg-slate-800 text-slate-400">STATUS: IDLE</span> | |
| <span class="badge bg-green-600/20 text-green-400">STEALTH ENABLED</span> | |
| <span class="badge bg-purple-600/20 text-purple-400">AUTO FALLBACK</span> | |
| </div> | |
| <!-- PANELS --> | |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-6"> | |
| <!-- RESULT --> | |
| <div class="lg:col-span-2 glass rounded-2xl p-6"> | |
| <div class="flex justify-between items-center mb-3"> | |
| <h2 class="text-xl font-semibold">Scraped Result</h2> | |
| <button onclick="clearResult()" class="text-sm text-slate-400 hover:text-white"> | |
| Clear | |
| </button> | |
| </div> | |
| <pre id="output" | |
| class="bg-black/60 rounded-xl p-4 text-sm max-h-[420px] overflow-auto scroll whitespace-pre-wrap"> | |
| Waiting for input... | |
| </pre> | |
| </div> | |
| <!-- LOGS --> | |
| <div class="glass rounded-2xl p-6"> | |
| <h2 class="text-xl font-semibold mb-3">Execution Logs</h2> | |
| <div id="logs" | |
| class="bg-black/60 rounded-xl p-4 text-sm h-[420px] overflow-auto scroll space-y-2"> | |
| <div class="text-slate-500">No logs yet.</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| const urlInput = document.getElementById("urlInput"); | |
| const output = document.getElementById("output"); | |
| const logsBox = document.getElementById("logs"); | |
| const btnText = document.getElementById("btnText"); | |
| const btnLoader = document.getElementById("btnLoader"); | |
| const scrapeBtn = document.getElementById("scrapeBtn"); | |
| const statusBadge = document.getElementById("statusBadge"); | |
| const engineBadge = document.getElementById("engineBadge"); | |
| const cfBadge = document.getElementById("cfBadge"); | |
| function setLoading(v) { | |
| btnLoader.classList.toggle("hidden", !v); | |
| btnText.textContent = v ? "Scraping..." : "Start Scraping"; | |
| scrapeBtn.disabled = v; | |
| scrapeBtn.classList.toggle("opacity-60", v); | |
| } | |
| function log(msg) { | |
| const div = document.createElement("div"); | |
| div.textContent = "• " + msg; | |
| div.className = "text-slate-300"; | |
| logsBox.appendChild(div); | |
| logsBox.scrollTop = logsBox.scrollHeight; | |
| } | |
| function clearResult() { | |
| output.textContent = "Waiting for input..."; | |
| logsBox.innerHTML = '<div class="text-slate-500">No logs yet.</div>'; | |
| statusBadge.textContent = "STATUS: IDLE"; | |
| statusBadge.className = "badge bg-slate-800 text-slate-400"; | |
| engineBadge.textContent = "ENGINE: IDLE"; | |
| cfBadge.textContent = "CF: UNKNOWN"; | |
| } | |
| async function startScrape() { | |
| const url = urlInput.value.trim(); | |
| if (!url.startsWith("http")) { | |
| output.textContent = "❌ Invalid URL (must start with http/https)"; | |
| statusBadge.textContent = "STATUS: ERROR"; | |
| statusBadge.className = "badge bg-red-600/20 text-red-400"; | |
| return; | |
| } | |
| clearResult(); | |
| setLoading(true); | |
| statusBadge.textContent = "STATUS: RUNNING"; | |
| statusBadge.className = "badge bg-blue-600/20 text-blue-400"; | |
| log("Scrape request started"); | |
| const fd = new FormData(); | |
| fd.append("url", url); | |
| try { | |
| const res = await fetch("/scrape", { method: "POST", body: fd }); | |
| const data = await res.json(); | |
| if (!data.success) throw new Error(data.error || "Failed"); | |
| output.textContent = JSON.stringify(data, null, 2); | |
| engineBadge.textContent = "ENGINE: " + data.engine.toUpperCase(); | |
| cfBadge.textContent = data.bypass === "attempted" | |
| ? "CF: BYPASS ATTEMPTED" | |
| : "CF: NOT REQUIRED"; | |
| statusBadge.textContent = "STATUS: SUCCESS"; | |
| statusBadge.className = "badge bg-green-600/20 text-green-400"; | |
| if (data.logs) data.logs.forEach(log); | |
| } catch (e) { | |
| output.textContent = "❌ ERROR:\n" + e.message; | |
| statusBadge.textContent = "STATUS: FAILED"; | |
| statusBadge.className = "badge bg-red-600/20 text-red-400"; | |
| log("Error: " + e.message); | |
| } finally { | |
| setLoading(false); | |
| } | |
| } | |
| </script> | |
| </body> | |
| </html> |