Why Hindi text and leading zeros break when you save a CSV (and the fixes)
CSV carries no encoding declaration and no column types, so Excel guesses both. Here is why Devanagari arrives as हि, why a 6-digit PIN…
BeeProton AI& Automation Solutions
A digital PDF gives up its text exactly; a scan gives up nothing. Learn to tell them apart in five seconds, extract tables to Excel, run the OCR route for scans including Hindi, and clean the result with pandas.
There are two kinds of PDF and only one of them will give you its text. A digital PDF — exported from Word, Tally, a bank's reporting system — stores actual characters, and extracting them is exact and instant. A scan stores a photograph of characters, and extraction returns nothing at all, not an approximation. Every frustrated hour spent on PDF extraction starts with not knowing which one is on screen, so test that first.
Open the file in any viewer and try to drag-select a line of text.
Two confirmations if you want them. Press Ctrl+F and search for a word you can clearly see on the page; no match means no text layer. Or zoom to 400%: digital text stays sharp because the glyphs are redrawn at every zoom level, while a scan turns into visible pixels.
There is a third case. A scan that has already been through OCR, as many office scanners do automatically, carries an invisible text layer behind the image. Ctrl+F works and extraction returns text, but that text holds whatever mistakes the original OCR made, and nothing marks them. If a document that looks like a scan extracts with l where 1 should be, that is what happened.
Mixed files are common too: a 40-page digital contract with two scanned signature pages. Test the page you need.
PDF to Text reads the characters stored in the file and puts them in an editable box you can copy or download as .txt. For a digital PDF this is character-for-character accurate, because nothing is being recognised; the text is simply read out of the file.
The one setting that matters is Preserve column spacing. Leave it ticked and the tool inserts spaces that mirror where each word sits horizontally on the page, so a table or a two-column layout stays visually aligned in the output. Untick it when you want flowing sentences and the extra gaps are just noise, which is the case for contracts, circulars and anything you plan to paste into a document.
Three honest limits:
fi as one character or soft hyphens mid-word.ToUnicode table, the text layer exists but maps to meaningless code points, and you get garbage even though the document is not a scan. There is no fix from the extraction side; treat that file as a scan and OCR it.No PDF contains a table. It contains words at coordinates, and sometimes lines drawn near them. PDF to Excel reconstructs the structure: it groups words into rows by their vertical position, then works out column boundaries from where words start and end horizontally, and writes the result to .xlsx or CSV. Each page becomes its own sheet unless you tick Put all pages in one sheet, which is what you want for a statement whose table runs across fourteen pages. Values that look numeric are written as real numbers, so SUM works immediately.
For a clean, machine-generated bank statement or invoice register, the output is usually 90% ready. For anything else, budget a few minutes of cleaning.
What helps: switch to CSV output and clean in pandas rather than fighting the spreadsheet, and tick the single-sheet option for continuing tables. What does not help: converting the PDF to something else first. Every route reads the same coordinates.
Two steps, both in the browser.
Step 1: render the pages as images. Open PDF to JPG, set the resolution to 300 DPI, and list the pages you need in the Pages box. Resolution is the decision that determines your accuracy: Tesseract wants roughly 20 pixels of lowercase letter height to work well, and at 150 DPI a 9 pt line gives it about 12. At 300 DPI it gets 25. If the page has fine print, or Devanagari with its matras and conjunct clusters, do not go below 300. For clean 12 pt text, 220 DPI is enough and renders faster. Where JPEG ringing around letter edges is visibly hurting the result, use PDF to PNG instead and accept files three to five times larger.
Step 2: recognise the text. Drop the images into AI OCR. It runs Tesseract as WebAssembly in your tab with fifteen languages available, including Hindi, Marathi, Bengali, Tamil, Telugu, Gujarati and Urdu.
Output is text, not a table. Paste it into a sheet and use Data → Text to Columns with the space delimiter, or clean it in pandas as below.
Rough ranges from typical documents. Your page will land somewhere near, not exactly on, these figures.
| Source | Realistic character accuracy | The practical effect |
|---|---|---|
| 300 DPI flatbed scan, printed English, 11 pt | 97–99% | a handful of errors per page |
| Straight phone photo, good light, printed English | 92–97% | a few dozen errors per page |
| Same photo, Hindi / Devanagari | noticeably lower | matras and conjuncts are where it fails |
| Ruled table, clean scan | text mostly right | row and column structure is lost |
| Thermal bill, faint carbon copy, dot-matrix print | poor | often faster to retype |
| Handwriting of any kind | unusable | the engine is trained on printed type |
Convert that percentage into work before you rely on it. A page holds around 2,000 characters, so 98% accuracy means roughly 40 errors on that page. The errors cluster exactly where you least want them: 5 and 6, 0 and O, 1 and l and I, 8 and B. For a bank statement or an invoice register this means OCR saves you the typing but not the checking. Never let an OCR'd figure go into an accounting entry or a tax return without someone reading it against the original.
Export CSV from PDF to Excel, then run this. It handles the three problems that turn up in almost every extraction: empty rows and columns, a header row left sitting in the data, and wrapped narration split across rows.
import pandas as pd
raw = pd.read_csv("statement.csv", header=None, dtype=str, keep_default_na=False)
# Drop what extraction left blank
raw = raw.replace("", pd.NA).dropna(how="all").dropna(axis=1, how="all")
# Promote the header row the tool wrote as data
raw.columns = [str(c).strip() for c in raw.iloc[0]]
df = raw.iloc[1:].reset_index(drop=True)
# Glue wrapped narration back onto the dated row above it
df["group"] = df["Date"].notna().cumsum()
df = (df.groupby("group")
.agg(Date=("Date", "first"),
Narration=("Narration", lambda s: " ".join(s.dropna())),
Debit=("Debit", "first"),
Credit=("Credit", "first"),
Balance=("Balance", "last"))
.reset_index(drop=True))
# "1,24,500.00 Dr" -> 124500.0
for col in ["Debit", "Credit", "Balance"]:
df[col] = pd.to_numeric(df[col].str.replace(r"[^0-9.\-]", "", regex=True),
errors="coerce")
df["Date"] = pd.to_datetime(df["Date"], dayfirst=True, errors="coerce")
print(len(df), "rows;", df["Date"].isna().sum(), "dates failed to parse")
Rename the columns to match what your statement actually produced before running the groupby. Two lines carry the work. df["Date"].notna().cumsum() is the standard trick for reattaching wrapped text: a cumulative sum over a boolean gives every continuation row the same group number as the dated row above it, so grouping on it rejoins them. And errors="coerce" turns anything unparseable into NaN instead of raising, which makes df["Debit"].isna().sum() your error count rather than a stack trace. Check it before you trust the numbers.
If dayfirst=True looks unnecessary, it is not: 03/04/2026 is 3 April in an Indian statement and 4 March to pandas' default parser. More of this in the pandas course.
PDF to Text returned nothing at all. What is wrong? The file is a scan, so there is no text layer to read. Render the pages with PDF to JPG at 300 DPI and run them through AI OCR.
Can I OCR a PDF in one step? Not here. Converting to images first is deliberate, because the rendering resolution is the single biggest factor in OCR accuracy and it should be your choice, not a hidden default.
Will OCR give me a spreadsheet from a scanned statement? No. OCR returns text in reading order and loses the column structure. Paste it into a sheet and split it with Data → Text to Columns, or clean it in pandas. Genuine table recognition from scans needs a paid service, and for a one-off statement it is usually faster to retype the figures than to fix a bad automated table.
Which is better for OCR input, JPG or PNG? PNG at 300 DPI is marginally better because there are no compression artefacts around letter edges, and it matters most on small text. JPG at 300 DPI is close enough for ordinary printed pages and produces much smaller files, which helps on a phone.
Written by Bablu Kumar Jha
Founder, BeeProton AI · Mumbai, Maharashtra, India
CSV carries no encoding declaration and no column types, so Excel guesses both. Here is why Devanagari arrives as हि, why a 6-digit PIN…
SSC, IBPS, RRB, UPSC and state PSC portals each want a photo and signature at fixed pixels and a fixed KB band. Here are the actual numbers…
JPEG throws detail away on purpose, PNG throws nothing away, and WEBP does both. Here is what the quality slider changes, why re-saving a J…
We use essential cookies to run this site and, on learning and tool pages, advertising cookies from partners like Google to keep our tools free. Your tool files are never uploaded. Learn more