Working demo · the exact test you asked for

PDF and web page → .txt, with the structure still intact

Your brief asked for a test run on two sample files, one PDF and one web page, showing the formatting carried over. That is exactly what is below — real inputs, real outputs, both downloadable.

Test 1 — PDF in, .txt out

↓ Source PDF ↓ Extracted .txt
Operations Report — sample source document

Regional Sales Q1
-----------------

[table 1]
--------------------------------------------------------------------
Region  Branch          Units  Revenue
--------------------------------------------------------------------
North   Delhi           1,240  892,400
        Chandigarh      860    611,200
        Lucknow         705    498,350
        North subtotal  2,805  2,001,950
West    Mumbai          2,110  1,580,500
        Pune            1,180  845,600
        Ahmedabad       930    662,100
        West subtotal   4,220  3,088,200
South   Bengaluru       1,750  1,298,000
        Chennai         1,105  812,350
        South subtotal  2,855  2,110,350
        GRAND TOTAL     9,880  7,200,500
--------------------------------------------------------------------

✓ heading underlined and on its own line · table columns still line up in a plain text editor · reading order preserved

Test 2 — web page in, .txt out

↗ Source page ↓ Extracted .txt
Unicode
========

  - Afrikaans
  - አማርኛ
  - العربية
  - অসমীয়া
  - Български
  - 閩東語 / Mìng-dĕ̤ng-ngṳ̄
  - ᏣᎳᎩ
  - کوردی

[table]
--------------------------------------------------------------------
Alias(es)         Universal Coded Character Set (UCS) ISO/IEC 10646
Languages         172 scripts ( list )
Standard          Unicode Standard
Encoding formats  UTF-8 UTF-16 GB18030 UTF-32 BOCU SCSU UTF-7
--------------------------------------------------------------------

✓ 1,040 lines · 14 tables rendered as aligned columns · UTF-8 throughout · right-to-left runs (Arabic, Kurdish) preserved

Deliberate choices

Tables excluded from the prose pass

First version mis-read a merged region cell as a heading and tore it out of its table. Table regions are now excluded from heading detection, then re-rendered as aligned columns.

Reading order, not page order

Blocks are sorted by vertical position, so tables appear where they belong rather than being dumped at the end of the page.

UTF-8 and RTL

Output is NFC-normalised UTF-8 with zero-width characters stripped. RTL runs are kept in logical order, which is what a text editor expects.

Runs on Windows, one command

python extract.py <file-or-url> out.txt — commented source, no build step.

The honest limit. This handles digital PDFs and web pages. Screenshots are a different problem — an image has no text layer, so it needs OCR, and OCR accuracy depends entirely on image quality. Your brief mentions screenshots, so that is worth settling before we start: I would add Tesseract for that path and be explicit that OCR output needs review, rather than quietly implying it is as reliable as the other two.