# Fix pdfplumber "extract_tables returns None" on a bordered fee schedule

## TL;DR
pdfplumber's table detection guesses from drawn lines or text alignment, and fee schedules often use whitespace layout or incomplete ruling lines, so the default strategy finds nothing. Try the text-based detection strategy with tuned tolerances; if the table still won't resolve, extract positioned words and rebuild rows from their coordinates yourself.

```text
extract_tables() returned None
```

## Steps
1. Retry with the text strategy and looser tolerances: call extract_tables with table_settings selecting the "text" strategy and increased x_tolerance and snap_tolerance.
   Expected: tables come back as lists of rows instead of None.
2. If that fails, pull extract_words for the page and inspect the coordinates around the fee rows.
   Expected: you can see the word positions that define the visual columns, even though no lines connect them.
3. Group words into rows by y-coordinate and split columns by x gaps, then assert the row count matches what you see visually.
   Expected: a faithful fee table you can validate row by row.
4. As a last resort, rasterize the page and run an OCR or vision table pass over the image.
   Expected: usable table data at the cost of speed and OCR noise.

## Use this when
- extract_tables returns None on a table that's obvious to a human reader
- Fee schedules, rate cards, or tier tables won't resolve with default settings
- The PDF uses whitespace or partial borders instead of a full grid

## Not for this skill when
- extract_tables returns wrong data rather than None (that's a tuning problem on a detected table)
- The PDF won't open at all (that's a structure/corruption problem)
- The "table" is actually an embedded image (skip straight to OCR)

## Variant phrasings
### pdfplumber find_tables empty
find_tables is the lower-level API behind extract_tables; same strategies apply.
### pdfplumber table detection not working
Detection is heuristic; the text strategy vs lines strategy choice matters most.
### extract text from pdf table python
If table detection keeps failing, positioned words plus manual row grouping is the reliable fallback.

## Why it happens
PDFs have no table concept: there are only positioned glyphs and vector lines. pdfplumber's default "lines" strategy looks for ruling lines forming cells; many real-world schedules draw partial lines or none at all. The "text" strategy instead aligns words into rows and columns, which matches how these documents are actually laid out, but its default tolerances are tuned for cleaner documents.

## Edge cases
- Merged header cells break column counts; handle headers as a special case.
- Multi-line row labels (for example, wrapped service descriptions) need y-grouping with a tolerance, not exact matches.
- Currency symbols and commas can split one amount across "columns"; normalize amounts after grouping.
- Always assert row counts against the visual; silent row merges are the failure mode here.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_P20PpLCTG3z-l_UhwyA4CA
