Extract handwritten text from PDF files using Mistral's Pixtral vision model in n8n workflows.
This project provides ready-to-use code for extracting handwritten text from PDFs using Mistral AI's Pixtral model within n8n workflows. Perfect for processing handwritten notes from reMarkable tablets or any other PDF with handwriting.
- ✍️ Handwriting OCR: Extracts handwritten text from PDF pages using Mistral Pixtral 12B
- 📄 Multi-page Support: Processes all pages in a PDF document
- 📝 Dual Output: Returns both JSON (structured data) and Markdown (formatted text)
- 🔄 n8n Integration: Designed specifically for n8n workflows
- 📧 Email Triggered: Works with incoming email attachments
- 🚀 Multiple Implementations: Choose between Python or JavaScript
Workflow:
- Email arrives with PDF attachment containing handwritten notes
- n8n workflow is triggered
- PDF is processed through Mistral Pixtral for OCR
- Extracted text is formatted as JSON and Markdown
- Result is forwarded to another service (e.g., note-taking app, CRM, etc.)
Get your API key from Mistral AI Console
- Self-hosted n8n (recommended) or n8n Cloud
- Version: 1.0.0 or higher
pip install pdf2image requests PillowYou may also need poppler-utils:
# Ubuntu/Debian
sudo apt-get install poppler-utils
# macOS
brew install poppler
# Docker
# Add to your n8n Dockerfile:
RUN apt-get update && apt-get install -y poppler-utilsnpm install pdf-lib
# or in n8n, these are typically pre-installed- Copy the Python code: Use
n8n_mistral_ocr.py - Set environment variable in n8n:
- Go to Settings > Environments
- Add:
MISTRAL_API_KEY=your_api_key_here
- Install dependencies in your n8n environment
- Create workflow (see below)
- Copy the JavaScript code: Use
n8n_simple_mistral_ocr.js - Set API key in the code or environment variable
- Create workflow (see below)
[Email Trigger] → [Extract Attachment] → [Python/JS Code] → [Process Output] → [Send to Service]
- Node Type: Email Trigger (IMAP)
- Configuration:
- Set up your email account
- Filter for emails with attachments
- Enable "Download Attachments"
- Node Type: Code
- Language: Python or JavaScript
- Code: Paste the content from
n8n_mistral_ocr.pyorn8n_simple_mistral_ocr.js
Environment Variable Configuration:
MISTRAL_API_KEY=your_mistral_api_key_hereThe code returns:
JSON Output:
{
"success": true,
"totalPages": 2,
"extractedText": "Full extracted text from all pages...",
"markdown": "# Extracted Handwritten Text\n\n...",
"pages": [
{
"page": 1,
"text": "Text from page 1...",
"dimensions": {
"width": 1654,
"height": 2339
}
}
],
"timestamp": "2025-11-23T12:00:00.000Z",
"model": "pixtral-12b-2409"
}Markdown Output:
# Extracted Handwritten Text
## Page 1
[Handwritten text from page 1]
---
## Page 2
[Handwritten text from page 2]
---
*Extracted on: 2025-11-23T12:00:00.000Z*
*Model: Mistral Pixtral 12B*Use HTTP Request, Webhook, or service-specific nodes to send the extracted text to your destination.
Example destinations:
- Notion (create a new page)
- Airtable (add record)
- Google Docs (append to document)
- Slack (send message)
- Email (send formatted email)
[Email Trigger]
↓
[Code: Mistral OCR]
↓
[Notion: Create Page]
- Title: Email subject
- Content: {{ $json.markdown }}
[Email Trigger]
↓
[Code: Mistral OCR]
↓
[Slack: Send Message]
- Channel: #notes
- Message:
New handwritten note:
{{ $json.extractedText }}
[Email Trigger]
↓
[Code: Mistral OCR]
↓
[HTTP Request]
- Method: POST
- URL: https://your-service.com/api/notes
- Body: {{ $json }}
In the code, you can modify:
Python:
# Line 34: Adjust DPI for quality vs speed
images = convert_from_bytes(pdf_bytes, dpi=300) # Higher = better quality, slowerJavaScript:
// Adjust the prompt for specific extraction needs
text: 'Extract all handwritten text, including margin notes and annotations...'Both implementations automatically process all pages. The results include:
- Per-page extracted text
- Combined text from all pages
- Page numbers and dimensions
Mistral Pixtral 12B Pricing (as of 2025):
- Input: ~$0.15 per 1M tokens
- Output: ~$0.45 per 1M tokens
Estimated cost per page:
- ~$0.001 - $0.005 per page (depending on image size and text length)
Solution: Set the environment variable in n8n settings or directly in the code.
Solution: Check that your email trigger is configured to download attachments. Verify the binary data path in the code matches your workflow.
Solution: Invalid API key. Verify your Mistral API key is correct and active.
Solution: Install poppler-utils on your system (see Prerequisites).
Solutions:
- Increase DPI in
convert_from_bytes()(Python) from 300 to 400-600 - Ensure source PDF has good resolution
- Try adjusting the Mistral prompt to be more specific about what to extract
Solutions:
- Process large PDFs in batches
- Increase n8n workflow timeout settings
- Consider splitting multi-page PDFs
Modify the extraction prompt for specific use cases:
# For forms
"Extract all handwritten text from this form, organized by field labels."
# For mathematical notation
"Extract all handwritten mathematical expressions and equations, preserving notation."
# For multi-language
"Extract all handwritten text. This may contain multiple languages including English and German."To process multiple PDFs in one workflow, use n8n's loop or batch processing nodes before the code node.
Customize the markdown format in the format_as_markdown() function:
def format_as_markdown(results):
markdown = "# Meeting Notes\n\n"
markdown += f"**Date**: {datetime.now().strftime('%Y-%m-%d')}\n\n"
# ... add your custom formatting
return markdownn8n_mistral_ocr.py- Python implementation (recommended)n8n_simple_mistral_ocr.js- Simplified JavaScript implementationn8n_mistral_pdf_ocr.js- Full-featured JavaScript implementationREADME.md- This fileexample_workflow.json- Example n8n workflow (coming soon)package.json- Node.js dependencies
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Submit a pull request
MIT License - feel free to use in your projects!
For issues and questions:
- Open an issue on GitHub
- Check n8n community forums
- Review Mistral AI documentation
- Mistral AI: For the Pixtral vision model
- n8n: For the workflow automation platform
- Inspired by various OCR and document processing workflows
- Initial release
- Python and JavaScript implementations
- Support for multi-page PDFs
- JSON and Markdown output formats
- n8n workflow integration
Happy OCR'ing! ✍️→📄→✨