Tutorials & Guides
How to Build a Local PDF-to-Markdown Converter and Table Extractor with Gemini 1.5 Flash and Python
Tired of broken layouts and mangled tables? Build a local Python CLI tool that uses Gemini's multi-modal context to cleanly parse complex PDFs into GitHub-Flavored Markdown.
Updated 10/13/2026
The Nightmare of PDF Parsing
Every developer who has ever tried to extract structured data from a PDF knows the sheer, unadulterated pain of the process. Standard Python open-source parsing libraries like PyPDF, pdfplumber, or Tabula look impressive in basic tutorials, but they completely collapse when faced with real-world multi-column layouts, nested tables, or headers.
You end up with broken strings, misaligned cells, and tables that look like someone put them through a digital blender.
With multi-modal LLMs, we can completely skip programmatic spatial heuristics. Gemini 1.5 Flash supports native file uploads (including PDFs) and has a context window of 1 million tokens. Even better, its API pricing is remarkably cheap, making it the perfect tool to digest complex PDF pages and spit out beautiful, clean GitHub-Flavored Markdown (GFM).
In this guide, we'll build a command-line script in Python that accepts a PDF file path, processes it through Gemini, extracts complex text and tables, and outputs clean Markdown files.
Prerequisites
Ensure you have the following installed on your machine:
- Python 3.10+
- A Google AI Studio API Key (set as an environment variable:
export GEMINI_API_KEY="your-api-key")
Step 1: Install the SDK and Dependencies
Let's set up a virtual environment and install Google's official generative AI SDK. Run the following commands in your terminal:
`bash
python3 -m venv venv
source venv/bin/activate
pip install google-generativeai pydantic
`
Note: The official `google-generativeai` package supports sending document formats like PDF directly to the model, handling document encoding and upload internally.
Step 2: Write the Basic Structure of the Script
Create a new file named pdf_to_markdown.py. First, let's configure the imports and parse the input command-line arguments:
`python
import os
import sys
import argparse
import google.generativeai as genai
Quick API key check if "GEMINI_API_KEY" not in os.environ: print("❌ Error: GEMINI_API_KEY environment variable is not set.") print("Please set it using: export GEMINI_API_KEY='your_key'") sys.exit(1)
genai.configure(api_key=os.environ["GEMINI_API_KEY"])
`
Now, let's set up an argument parser to make this a convenient CLI utility:
`python
def parse_args():
parser = argparse.ArgumentParser(
description="Convert a local PDF into clean, structured Markdown using Gemini 1.5 Flash."
)
parser.add_argument("pdf_path", type=str, help="Path to the local PDF file")
parser.add_argument(
"--output", "-o", type=str, help="Path to save the output markdown file (optional)"
)
return parser.parse_args()
`
Step 3: Crafting the Prompt for Perfect Extraction
We don't want Gemini to merely summarise the PDF or give us an approximation. We need it to act as an advanced document engine. We need to explicitly instruct it to preserve structures, convert tables into well-formed Markdown grids, and avoid hallucinating data points.
Add this function to prepare our generation context:
`python
def get_extraction_prompt():
return (
"You are an expert document parser. Your goal is to convert this entire PDF into "
"clean, structured, and accurate GitHub-Flavored Markdown (GFM).\n\n"
"Instructions:\n"
"1. Retain all header hierarchies (using #, ##, ### as appropriate).\n"
"2. Identify tabular structures and output them as valid Markdown tables. Ensure header "
"rows are separated correctly and cells align with their respective columns. Do not skip rows.\n"
"3. Extract lists, code blocks, bullet points, and citations precisely as they appear.\n"
"4. If you encounter images with diagrams or charts, describe the chart or diagram briefly "
"inside a markdown blockquote starting with '> [Visual Asset Description]'.\n"
"5. Do NOT hallucinate content or omit body text. Preserve the original language and narrative flow."
)
`
Step 4: Interfacing with the Gemini API
Now, let's write the execution code. Because Gemini 1.5 Flash natively accepts document files, we can use the files.upload() API helper. This uploads the document securely to Google's temporary storage, allowing the model to process multi-page PDFs with minimal latency.
`python
def process_pdf(pdf_path):
if not os.path.exists(pdf_path):
print(f"❌ Error: File not found at {pdf_path}")
sys.exit(1)
print(f"📦 Uploading '{pdf_path}' to Google AI File API...") uploaded_file = genai.upload_file(path=pdf_path, mime_type="application/pdf") print(f"🔄 File uploaded successfully. URI: {uploaded_file.uri}")
Initialize the Gemini 1.5 Flash model model = genai.GenerativeModel("gemini-1.5-flash")
print("🧠 Processing PDF document and converting to Markdown...") response = model.generate_content( [uploaded_file, get_extraction_prompt()] )
Clean up file in the Google cloud storage after processing genai.delete_file(uploaded_file.name) print("🧹 Cleaned up processed file from AI storage container.")
return response.text
`
Step 5: Tying it All Together
Finally, we will add the main entry point to handle output writing, allowing developers to either stream the output to standard out or save it directly to disk.
`python
def main():
args = parse_args()
try:
markdown_output = process_pdf(args.pdf_path)
output_destination = args.output
if not output_destination:
# Auto-generate a fallback output filename
base_name = os.path.splitext(args.pdf_path)[0]
output_destination = f"{base_name}_extracted.md"
with open(output_destination, "w", encoding="utf-8") as f: f.write(markdown_output) print(f"🎉 Conversion complete! Markdown saved to: {output_destination}")
except Exception as e: print(f"❌ Extraction failed due to an error: {e}") sys.exit(1)
if __name__ == "__main__":
main()
`
Running Your Converter
Let's put this to the test. Find a multi-page PDF with some tricky tables—like a financial report or technical specification document—and run your new script:
`bash
python pdf_to_markdown.py doc/q3-performance-report.pdf -o results/report.md
`
The output markdown file will contain highly accurate text extraction and clean markdown tables, eliminating the tedious work of manual data copying.
Handling Errors and Scaling
If you experience timeout errors or hit API limits when parsing massive PDFs (over 100 pages), or if you run into authentication issues, check out our Gemini troubleshooting platform for solutions. For huge documents, splitting your PDF into 20-page chunks using an open-source library like pypdf before uploading each chunk sequentially is an excellent way to maintain reliable, snappy outputs.
Keep going
Build something with the prompt generator, decode the jargon in the glossary, or compare the tools on our platform deep-dives.
Set up your AI once so you repeat yourself less.
Try AI Setup ProfileTickd is independent and not affiliated with any AI company.