How to extract data from raw text: methods, code and best practices
For analysts, developers and operations teams turning emails, reports, OCR output and other raw text into fields a system can use: the methods, working Python examples, and how to keep the results accurate.

Key takeaways
- Raw text is unformatted text with no labels or structure, such as an email body, a support ticket, a report, or the output of OCR on a scanned page.
- Extracting data from it means turning that text into named fields: dates, amounts, names, account numbers, clauses.
- Use regular expressions for fixed patterns, NLP entity recognition (such as spaCy) for names, places and dates, and large language models for fields that need context.
- Whatever the method, validate the output: check types and formats, cross-check totals and route low-confidence values to a person.
- If the raw text came from a PDF or scan, you lose the layout. For documents, layout-aware extraction is more accurate than working from flattened text.
On this page
Extracting data from raw text means finding specific values, such as dates, amounts, names and account numbers, in unformatted text and turning them into labeled fields a system can use. The three main methods are regular expressions for fixed patterns, natural language processing (NLP) for entities like people and organizations, and large language models (LLMs) for fields that need context. Whatever method you use, validate the output before it reaches your systems.
This guide explains what raw text is, compares the methods with working Python examples, walks through a step-by-step process, and covers the checks that keep the data accurate.
What is raw text?#
Raw text is text with no formatting, labels or structure. Examples:
- Email and chat message bodies
- Support tickets and call transcripts
- Reports, notes and letters
- Log files
- The text OCR returns from a scanned document
A person can read raw text and understand that "net 30" is a payment term or that "$4,812.30" is an amount due. Software can't, until those values are found and labeled.
Methods for extracting data from raw text#
| Method | Best for | Watch out for |
|---|---|---|
| Regular expressions | Fixed patterns: dates, emails, phone numbers, invoice or policy IDs | Breaks when the format varies |
| NLP entity recognition | People, organizations, places, dates, money | Generic models don't know your domain labels |
| Large language models | Fields that need context: "the renewal date", "the party responsible for repairs" | Can return confident wrong answers; needs validation |
| Layout-aware document AI | Text that came from PDFs and scans, including tables | Needs a model for the document type |
Regular expressions
Regex is the fastest option for values with a predictable shape:
import re
text = """Hi team, please pay invoice INV-20418 for $4,812.30 by 10/12/2026.
Questions to billing@harborstreet.example or (207) 555-0143."""
invoice_ids = re.findall(r"\bINV-\d+\b", text)
amounts = re.findall(r"\$\d{1,3}(?:,\d{3})*(?:\.\d{2})?", text)
dates = re.findall(r"\b\d{2}/\d{2}/\d{4}\b", text)
emails = re.findall(r"[\w.+-]+@[\w-]+\.[\w.]+", text)
print(invoice_ids, amounts, dates, emails)
# ['INV-20418'] ['$4,812.30'] ['10/12/2026'] ['billing@harborstreet.example']
Keep patterns strict and test them on real samples. A loose amount pattern will happily match a phone number.
NLP entity recognition with spaCy
Named entity recognition (NER) finds entities by meaning, not just shape. spaCy's pre-trained English pipelines label people, organizations, places, dates, money and more:
import spacy
# first run: python -m spacy download en_core_web_sm
nlp = spacy.load("en_core_web_sm")
doc = nlp("Harbor Street Supply signed a lease with Bayside Foods in Portland on March 3, 2026 for $9,150 a month.")
for ent in doc.ents:
print(ent.text, ent.label_)
Typical output labels Harbor Street Supply and Bayside Foods as ORG, Portland as GPE, March 3, 2026 as DATE and $9,150 as MONEY, though small models make mistakes. For labels specific to your business, such as policy number or loan type, you train a custom model on annotated examples. See our guide to text annotation.
Large language models with a schema
LLMs can pull fields that depend on context, like "who pays for repairs" in a lease. The reliable pattern is to define the output schema, ask the model to return JSON matching it, and validate the result:
from datetime import date
from pydantic import BaseModel, ValidationError
class LeaseTerms(BaseModel):
tenant: str
landlord: str
start_date: date
monthly_rent: float
repairs_responsibility: str
# response_text is the JSON string returned by the LLM of your choice
try:
terms = LeaseTerms.model_validate_json(response_text)
except ValidationError as err:
send_to_review(response_text, err) # don't trust output that fails the schema
Schema validation catches missing fields and wrong types, but not a plausible wrong value. For anything that drives a decision, add business rules and human review.
Step by step: extracting data from raw text#
- Define the fields. List every field you need, its type and format, and an example.
- Get clean text. Normalize encoding, whitespace and line breaks. If the text comes from scans, check OCR quality first; bad OCR can't be fixed downstream.
- Choose the method per field. Regex for IDs and dates, NER for names, an LLM or trained model for context-dependent fields. Mixing methods is normal.
- Extract. Run the extraction and keep a pointer from each value back to where it appeared in the text.
- Normalize. Convert dates to ISO format, amounts to numbers, names to a standard form.
- Validate. Check types, ranges and required fields. Cross-check related values: do the line items add up to the total?
- Review exceptions. Send values that fail a check or have low confidence to a person.
- Load. Push clean data to your system through an API, a file export or a database insert.
When the raw text came from a document#
A lot of "raw text" is really a document that's been flattened: the output of OCR on an invoice, a bank statement or a form. Flattening throws away the layout, and the layout carries meaning. Which number is in the "Total" column? Which date belongs to which transaction row?
For documents, layout-aware extraction is more accurate than regex or NLP over flattened text. Intelligent document processing reads text and position together, extracts fields and full tables, and gives a confidence score for each value. Docsumo, for example, has pre-trained models for bank statements, invoices, tax forms and ACORD forms, and reports 99% field-level accuracy on 250+ document types.
Challenges and how to handle them#
- Messy input. Typos, OCR errors and inconsistent formats. Normalize first and keep patterns tolerant but tested.
- Ambiguity. "03/04/2026" is March 4 in the US and April 3 elsewhere. Decide rules per source.
- Changing formats. Senders change templates and wording. Monitor extraction failure rates so you notice.
- Sensitive data. Emails and documents contain personal data. Mask what you don't need and choose tools with the right security certifications.
Best practices after extraction#
- Keep the source link. Store where each value came from for audits and corrections.
- Measure accuracy per field. Some fields will be near perfect and others weak; fix the weak ones.
- Log corrections. Reviewer fixes are training data for the next model version.
- Automate the loop. Extraction, validation, review and export should run as one workflow, not four manual steps.
The bottom line#
Start with the simplest method that works for each field: regex for patterns, NLP for entities, LLMs for context. Validate everything. And if your raw text is really a document, extract from the document itself rather than its flattened text. To see how Docsumo handles your documents, book a demo.
Frequently asked questions#
What is raw text?
Raw text is plain text without formatting, labels or structure, such as a message body, a transcript, a log or the text OCR returns from a scanned page. A person can read it, but software can't use it until the values are identified and labeled.
How do I extract data from raw text in Python?
Use the re module for fixed patterns like dates and IDs, spaCy for named entities like people, organizations and money, and a large language model with a defined output schema for fields that need context. Validate the output with a library like pydantic.
Can an LLM extract data from text accurately?
Often, yes, especially with a clear schema and examples. But LLMs can return plausible wrong values, so validate every field and keep a person in the loop for values that fail checks.
What's the best way to extract data from text in PDFs?
Don't flatten the PDF to raw text first if you can avoid it. Tables and field positions carry meaning. Use a tool that reads layout as well as text. See data extraction from PDF.
Sources
- Python documentation: re module
- spaCy: linguistic features, named entities
- Pydantic documentation: models and validation
First published . Last updated .