Image to Text – Free OCR Tool | SnapToolSet
OCR Powered by Tesseract

Extract Text from
Any Image

Drop a screenshot, photo, or scanned document — get selectable, copyable text in seconds. Runs 100% in your browser.

50+ Languages
100% Private
JPG · PNG · WEBP · BMP · GIF
No upload · No server
Input Image
🖼
Drop image here
or click to browse — or paste (Ctrl+V)
JPGPNG WEBPBMP GIFTIFF
Loaded image
Initialising… 0%
Extracted Text
Confidence
📝

Extracted text will appear here.
Load an image and click Extract Text.

Words: 0 Chars: 0 Lines: 0
SnapToolSet — OCR powered by Tesseract.js. All processing runs locally in your browser.
No files are uploaded. No data is collected or stored on any server.
`; downloadFile(html, getBaseName() + '.doc', 'application/msword'); showToast('✅ .doc downloaded!', 'ok'); });/* ── PRINT ── */ printBtn.addEventListener('click', () => { const text = extractedText.value; if (!text) { showToast('Nothing to print.', 'err'); return; } const win = window.open('', '_blank'); win.document.write(`SnapToolSet – Extracted Text${escapeHtml(text)}`); win.document.close(); win.print(); });/* ── HISTORY ── */ function addToHistory(entry) { state.history.unshift(entry); if (state.history.length > 10) state.history = state.history.slice(0, 10); saveHistory(); renderHistory(); }function renderHistory() { if (!state.history.length) { historySection.style.display = 'none'; return; } historySection.style.display = ''; histList.innerHTML = ''; state.history.forEach(h => { const item = document.createElement('div'); item.className = 'hist-item'; const excerpt = h.text.trim().slice(0, 120) + (h.text.trim().length > 120 ? '…' : ''); item.innerHTML = ` ${h.name}
${h.name}
${excerpt || '(no text found)'}
${h.ts} · ${h.lang} · ${h.confidence}% confidence
`; histList.appendChild(item); }); }histList.addEventListener('click', e => { const btn = e.target.closest('.hist-btn'); if (!btn) return; const id = parseInt(btn.dataset.id); const action = btn.dataset.action; const entry = state.history.find(h => h.id === id); if (!entry) return; if (action === 'restore') { showText(entry.text); showConfidence(entry.confidence); updateStats(entry.text); showToast('✅ Text restored from history.', 'ok'); window.scrollTo({ top: 0, behavior: 'smooth' }); } else if (action === 'delete') { state.history = state.history.filter(h => h.id !== id); saveHistory(); renderHistory(); showToast('🗑 Entry removed.', 'ok'); } });clearHistBtn.addEventListener('click', () => { state.history = []; saveHistory(); renderHistory(); showToast('🗑 History cleared.', 'ok'); });function saveHistory() { const lite = state.history.map(h => ({ ...h, thumb: h.thumb.slice(0, 200) })); try { localStorage.setItem('tl_history', JSON.stringify(lite)); } catch {} }/* ── HELPERS ── */ function formatBytes(b) { if (b >= 1048576) return (b/1048576).toFixed(1) + ' MB'; if (b >= 1024) return (b/1024).toFixed(1) + ' KB'; return b + ' B'; } function getBaseName() { return (state.imageName || 'extracted').replace(/\.[^.]+$/, ''); } function downloadFile(content, filename, mime) { const blob = new Blob([content], { type: mime }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = filename; a.click(); URL.revokeObjectURL(a.href); } function escapeHtml(s) { return s.replace(/&/g,'&').replace(//g,'>'); }/* ── TOAST ── */ let toastTimer; function showToast(msg, type = 'ok') { const el = document.getElementById('toast'); el.textContent = msg; el.className = `show t-${type}`; clearTimeout(toastTimer); toastTimer = setTimeout(() => el.className = '', 3400); }/* ── INIT ── */ renderHistory();