Free WP Web Scraper Tool - Extract HTML, Emails & Data Instantly
AI Magic Extract
Ask AI
📝 Summary
🏷️ Products
Manual Selector
CSS
REGEX
How to Use This Tool Start extracting data in 3 simple steps. No technical knowledge required.
1
Load Content Enter a URL and click Fetch to load the website via proxy. Alternatively, paste raw HTML code directly into the "Source" editor.
2
Extract Data Use Quick Extract buttons for common items (Links, Emails), or use AI Magic Extract to find specific data like "prices".
3
Export Review your results in the list view. Click Export to download the data as a JSON file or CSV for Excel/Google Sheets.
Why use this Free WP Scraper? Built for developers, SEO experts, and marketers who need data fast. No servers, no setup, just instant extraction from WordPress and HTML sites.
100% Client-Side Everything runs in your browser. Your data never leaves your computer, making it secure and private by default.
AI Powered Extraction Struggling with complex HTML? Just ask the AI to "Find all prices" or "Summarize the reviews" and watch the magic happen.
WP Optimized Specifically tuned for WordPress structures. Easily extract post titles, WooCommerce products, metadata, and custom fields.
Frequently Asked Questions Is this WP Web Scraper Tool free? Yes, the tool is completely free to use. You can extract unlimited data points from HTML source code or public URLs without any cost.
How do I scrape a WordPress site? Simply enter the URL of the WordPress site above and click "Fetch". Once the HTML loads, you can use the built-in "Quick Extract" buttons or type standard WordPress CSS selectors like .entry-title or .product-price.
Does it work on password protected sites? The "Fetch URL" feature uses public proxies, so it cannot access private data. However, you can manually log in to a site, view the source code (Ctrl+U), copy it, and paste it into the "Source Code" editor to scrape it securely.
Can I export scraped data to Excel or CSV? Absolutely. Once you scrape data, simply click the "Export" button on the right to download your results in JSON or CSV format, which is fully compatible with Excel and Google Sheets.
Does this work with WooCommerce products? Yes! You can specifically target WooCommerce elements using selectors like .product-title, .price, or .woocommerce-LoopProduct-link to extract product catalogs instantly.
Do I need coding skills to use this scraper? No coding is required. You can use our "Quick Extract" buttons for common data, or use manual selectors to find specific content.
\n`;
updateStats();
quickScrape('headings');
}function updateStats() {
const len = htmlInput.value.length;
document.getElementById('editorStats').textContent = `${len.toLocaleString()} chars`;
}function parseHTML() {
const parser = new DOMParser();
return parser.parseFromString(htmlInput.value || '', 'text/html');
}async function fetchFromUrl() {
let url = urlInput.value.trim();
if (!url) return showToast("Please enter a URL first.", true);
if (!/^https?:\/\//i.test(url)) {
url = 'https://' + url;
urlInput.value = url;
}const btn = document.getElementById('fetchBtn');
const originalContent = btn.innerHTML;
btn.innerHTML = '
';
btn.disabled = true;try {
let content = null;
// Proxy 1
try {
const proxyUrl = `https://api.allorigins.win/get?url=${encodeURIComponent(url)}`;
const response = await fetch(proxyUrl);
if (response.ok) {
const data = await response.json();
if (data.contents) content = data.contents;
}
} catch (e) { console.warn("Proxy 1 failed"); }// Proxy 2 Fallback
if (!content) {
try {
const proxyUrl = `https://corsproxy.io/?` + encodeURIComponent(url);
const response = await fetch(proxyUrl);
if (response.ok) content = await response.text();
} catch (e) { console.warn("Proxy 2 failed"); }
}if (content) {
htmlInput.value = content;
updateStats();
quickScrape('links');
if(!document.getElementById('view-preview-container').classList.contains('hidden')) {
previewFrame.srcdoc = content;
}
} else {
throw new Error("Proxies failed");
}
} catch (err) {
showToast("Could not fetch URL. Try manual copy/paste.", true);
} finally {
btn.innerHTML = originalContent;
btn.disabled = false;
}
}function quickScrape(type) {
const doc = parseHTML();
let items = [];
lastAction = { type: 'quick', selector: type };
let icon = '';if (type === 'links') {
items = Array.from(doc.querySelectorAll('a[href]')).map(el => ({ label: 'Link', value: el.getAttribute('href'), tag: 'A' }));
icon = 'fa-link';
} else if (type === 'images') {
items = Array.from(doc.querySelectorAll('img[src]')).map(el => ({ label: 'Image', value: el.getAttribute('src'), tag: 'IMG' }));
icon = 'fa-image';
} else if (type === 'headings') {
items = Array.from(doc.querySelectorAll('h1, h2, h3')).map(el => ({ label: el.tagName, value: el.innerText.trim(), tag: el.tagName }));
icon = 'fa-heading';
} else if (type === 'emails') {
const matches = htmlInput.value.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/gi) || [];
items = [...new Set(matches)].map(e => ({ label: 'Email', value: e, tag: '@' }));
icon = 'fa-at';
} else if (type === 'phones') {
// Basic international phone regex
const matches = htmlInput.value.match(/[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}/g) || [];
items = [...new Set(matches)].map(p => ({ label: 'Phone', value: p.trim(), tag: 'Tel' }));
icon = 'fa-phone';
} else if (type === 'social') {
const socialDomains = ['facebook.com', 'twitter.com', 'linkedin.com', 'instagram.com', 'youtube.com', 'tiktok.com', 'pinterest.com'];
const links = Array.from(doc.querySelectorAll('a[href]'));
items = links.filter(el => {
const href = el.getAttribute('href').toLowerCase();
return socialDomains.some(domain => href.includes(domain));
}).map(el => ({
label: 'Social',
value: el.getAttribute('href'),
tag: 'Soc'
}));
// Remove duplicates
items = items.filter((v,i,a)=>a.findIndex(t=>(t.value === v.value))===i);
icon = 'fa-share-nodes';
} else if (type === 'meta') {
const metas = Array.from(doc.querySelectorAll('meta[name], meta[property]'));
items = metas.map(el => ({
label: el.getAttribute('name') || el.getAttribute('property'),
value: el.getAttribute('content'),
tag: 'Meta'
})).filter(i => i.value && i.label); // Only keep valid meta tags
icon = 'fa-tags';
} else if (type === 'paragraphs') {
items = Array.from(doc.querySelectorAll('p')).map(el => ({
label: 'Para',
value: el.innerText.trim(),
tag: 'P'
})).filter(i => i.value.length > 0); // Remove empty paragraphs
icon = 'fa-paragraph';
}renderResults(items, icon);
}function customScrape() {
const selector = selectorInput.value;
if(!selector) return;
const isRegex = regexToggle.checked;
let items = [];
if(isRegex) {
lastAction = { type: 'regex', selector: selector };
try {
const regex = new RegExp(selector, 'g');
const matches = htmlInput.value.match(regex) || [];
items = [...new Set(matches)].map(m => ({ label: 'Match', value: m, tag: 'Rgx' }));
renderResults(items, 'fa-code');
} catch(e) { showToast("Invalid Regex", true); }
} else {
lastAction = { type: 'css', selector: selector };
try {
const doc = parseHTML();
items = Array.from(doc.querySelectorAll(selector)).map(el => ({
label: el.tagName.toLowerCase(),
value: el.innerText.trim() || el.getAttribute('src') || el.getAttribute('href'),
tag: el.tagName
}));
renderResults(items, 'fa-crosshairs');
} catch(e) { showToast("Invalid Selector", true); }
}
}// --- AI Logic ---
function setAiPrompt(text) {
aiPromptInput.value = text;
askGemini();
}async function askGemini() {
const prompt = aiPromptInput.value.trim();
if (!prompt || !htmlInput.value) return showToast("Load HTML & enter prompt first.", true);
const btn = document.getElementById('aiBtn');
const originalText = btn.innerText;
btn.innerText = "Thinking...";
btn.disabled = true;
lastAction = { type: 'ai', selector: prompt };try {
const doc = parseHTML();
doc.querySelectorAll('script, style, svg').forEach(el => el.remove());
let context = doc.body ? doc.body.innerText : doc.documentElement.innerText;
if(context.length > 300000) context = context.substring(0, 300000);// API Key inserted successfully
const apiKey = "AIzaSyBbZb_HpXJVu2HxQt6MwfMN6bcO9a6IuVY";
if(!apiKey) {
throw new Error("AI Service not configured. Publisher: Please insert API Key in code.");
}const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-09-2025:generateContent?key=${apiKey}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
contents: [{ parts: [{ text: `Context: ${context}\n\nRequest: ${prompt}` }] }],
systemInstruction: { parts: [{ text: `Extract data as JSON: { "items": [{ "label": "Label", "value": "Value" }] }` }] },
generationConfig: { responseMimeType: "application/json" }
})
});
if (!response.ok) throw new Error("API Request Failed");const data = await response.json();
const json = JSON.parse(data.candidates?.[0]?.content?.parts?.[0]?.text);
if(json.items) renderResults(json.items, 'fa-sparkles');
} catch(e) {
showToast(e.message, true);
}
finally { btn.innerText = originalText; btn.disabled = false; }
}function renderResults(items, iconClass) {
currentData = items;
resultsList.innerHTML = '';
if(!items || items.length === 0) {
emptyState.classList.remove('hidden');
statsBar.classList.add('hidden');
return;
}
emptyState.classList.add('hidden');
statsBar.classList.remove('hidden');
resultCount.innerText = `${items.length} items`;
if(document.getElementById('tourOverlay').classList.contains('tour-active') && currentTourStep === 4) {
nextTourStep();
}let color = 'text-indigo-400';
if(iconClass === 'fa-sparkles') color = 'text-amber-400';items.forEach((item, i) => {
const div = document.createElement('div');
div.className = "bg-slate-800 border border-slate-700 p-3 rounded flex gap-3 items-start group animate-fade-in";
div.style.animationDelay = `${i * 0.02}s`;
const safeValue = encodeURIComponent(item.value).replace(/'/g, "%27");
div.innerHTML = `
${escapeHtml(item.label || item.tag)}
${escapeHtml(item.value)}
`;
resultsList.appendChild(div);
});
}// --- Utils ---
function clearAll() {
htmlInput.value = '';
urlInput.value = '';
resultsList.innerHTML = '';
emptyState.classList.remove('hidden');
statsBar.classList.add('hidden');
currentData = [];
updateStats();
}
function escapeHtml(text) { if(!text) return ''; return text.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); }
function copyToClipboard() { copyText(JSON.stringify(currentData, null, 2)); }
function downloadJSON() { const a = document.createElement('a'); a.href = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(currentData)); a.download = 'data.json'; a.click(); }
function downloadCSV() {
const rows = ["Label,Value"];
currentData.forEach(r => rows.push(`"${(r.label||'').replace(/"/g,'""')}","${(r.value||'').replace(/"/g,'""')}"`));
const a = document.createElement('a');
a.href = "data:text/csv;charset=utf-8," + encodeURIComponent(rows.join('\n'));
a.download = 'data.csv'; a.click();
}
function openCodeModal() {
const modal = document.getElementById('codeModal');
let code = "import requests\nfrom bs4 import BeautifulSoup\n\n# Your target URL\nurl = 'URL_HERE'\nres = requests.get(url)\nsoup = BeautifulSoup(res.text, 'html.parser')\n\n";
if (lastAction.type === 'css') code += `# Extracting: ${lastAction.selector}\ndata = [x.text.strip() for x in soup.select('${lastAction.selector}')]\nprint(data)`;
else if (lastAction.type === 'quick') code += `# Quick extract: ${lastAction.selector}\n# ... (Standard BS4 logic here)`;
else code += "# No recent action recorded to generate specific code.";
document.getElementById('generatedCodeBlock').textContent = code;
Prism.highlightElement(document.getElementById('generatedCodeBlock'));
modal.classList.add('active');
}
function closeCodeModal() { document.getElementById('codeModal').classList.remove('active'); }
function copyCode() { copyText(document.getElementById('generatedCodeBlock').textContent); }
// Editor Tools
function formatHTML() { htmlInput.value = htmlInput.value.replace(/>\s*\n<"); updateStats(); }
function compactHTML() { htmlInput.value = htmlInput.value.replace(/\s+/g, ' '); updateStats(); }
function cleanHTML() { const doc = parseHTML(); doc.querySelectorAll('script, style').forEach(e=>e.remove()); htmlInput.value = doc.body.innerHTML; updateStats(); }
function toggleRegexMode() {
const isRegex = regexToggle.checked;
selectorInput.placeholder = isRegex ? "Regex Pattern (e.g. \\d+)" : "CSS Selector (e.g. .price)";
document.getElementById('selectorIcon').className = isRegex ? "fa-solid fa-code text-pink-500" : "fa-solid fa-crosshairs text-slate-500";
}// Init
loadSample();