Parse Property Appraisals into Structured Data for Your Real Estate Platform

8 min read Document Extraction

Appraisals Are Data-Rich but Machine-Hostile

Property appraisal documents contain exactly the data a real estate platform needs — property addresses, valuations, lot sizes, room counts, comparable sales, condition assessments. The problem is getting that data out.

Appraisals follow general conventions but vary in format. A residential appraisal from one firm uses different section headings, different table layouts, and different field placements than one from another firm. Government forms like the URAR have specific layouts, but scanned versions come in rotated, with varying scan quality.

Building a parser for each appraisal format isn’t practical. You need extraction that adapts to the document.

Property Appraisal Schema

The Document Extraction API uses schema-based extraction. Define the fields you need and let the parser find them in any appraisal format:

import { IterationLayer } from "iterationlayer";
const client = new IterationLayer({ apiKey: "YOUR_API_KEY" });

const { data } = await client.extract({
  files: [
    { type: "url", name: "appraisal.pdf", url: "https://example.com/appraisal.pdf" }
  ],
  schema: {
    fields: [
      {
        name: "property_address",
        type: "ADDRESS",
        description: "Address of the appraised property",
        is_required: true,
      },
      {
        name: "appraisal_date",
        type: "DATE",
        description: "Date of the appraisal",
        is_required: true,
      },
      {
        name: "appraised_value",
        type: "CURRENCY_AMOUNT",
        description: "Final appraised market value of the property",
        is_required: true,
      },
      {
        name: "currency",
        type: "CURRENCY_CODE",
        description: "Currency of the appraisal",
      },
      {
        name: "property_type",
        type: "ENUM",
        description: "Type of property",
        values: ["single_family", "condo", "townhouse", "multi_family", "land", "commercial", "other"],
      },
      {
        name: "year_built",
        type: "INTEGER",
        description: "Year the property was built",
      },
      {
        name: "living_area_in_sq_ft",
        type: "DECIMAL",
        description: "Total living area in square feet",
      },
      {
        name: "lot_size_in_sq_ft",
        type: "DECIMAL",
        description: "Total lot size in square feet",
      },
      {
        name: "bedrooms",
        type: "INTEGER",
        description: "Number of bedrooms",
      },
      {
        name: "bathrooms",
        type: "DECIMAL",
        description: "Number of bathrooms (half baths as 0.5)",
      },
      {
        name: "condition",
        type: "ENUM",
        description: "Overall property condition",
        values: ["excellent", "good", "average", "fair", "poor"],
      },
      {
        name: "comparable_sales",
        type: "ARRAY",
        description: "Comparable property sales used in the appraisal",
        item_schema: {
          fields: [
            { name: "address", type: "ADDRESS", description: "Address of the comparable property" },
            { name: "sale_price", type: "CURRENCY_AMOUNT", description: "Sale price" },
            { name: "sale_date", type: "DATE", description: "Date of sale" },
            { name: "living_area_in_sq_ft", type: "DECIMAL", description: "Living area in square feet" },
          ],
        },
      },
    ],
  },
});

Structured Property Data

The response gives you typed, structured data:

{
  "propertyAddress": {
    "type": "ADDRESS",
    "value": {
      "street": "742 Evergreen Terrace",
      "city": "Springfield",
      "region": "IL",
      "postal_code": "62704",
      "country": "US"
    },
    "confidence": 0.95
  },
  "appraisedValue": {
    "type": "CURRENCY_AMOUNT",
    "value": 385000,
    "confidence": 0.96
  },
  "livingAreaInSqFt": {
    "type": "DECIMAL",
    "value": 2150,
    "confidence": 0.93
  },
  "comparableSales": {
    "type": "ARRAY",
    "value": [
      [
        { "value": { "street": "318 Maple Drive", "city": "Springfield", "region": "IL", "postal_code": "62701", "country": "US" }, "confidence": 0.91 },
        { "value": 372000, "confidence": 0.94 },
        { "value": "2025-11-20", "confidence": 0.92 },
        { "value": 2050, "confidence": 0.90 }
      ]
    ],
    "confidence": 0.91
  }
}

The ADDRESS fields come back decomposed — street, city, state, zip, country. The CURRENCY_AMOUNT is a number, not a formatted string. The ARRAY handles the comparable sales table regardless of how many comps the appraisal includes.

Extracting Comparable Sales in Detail

The comparable sales section is the most valuable — and most complex — part of an appraisal. Appraisers typically include 3 to 6 comparable properties, each with an address, sale price, sale date, square footage, lot size, and adjustment amounts.

A richer comparable sales schema captures the adjustments that appraisers make when comparing properties:

{
  name: "comparable_sales",
  type: "ARRAY",
  description: "Comparable property sales used in the appraisal",
  item_schema: {
    fields: [
      { name: "address", type: "ADDRESS", description: "Address of the comparable property" },
      { name: "sale_price", type: "CURRENCY_AMOUNT", description: "Sale price of the comparable" },
      { name: "sale_date", type: "DATE", description: "Date of the comparable sale" },
      { name: "living_area_in_sq_ft", type: "DECIMAL", description: "Living area in square feet" },
      { name: "lot_size_in_sq_ft", type: "DECIMAL", description: "Lot size in square feet" },
      { name: "bedrooms", type: "INTEGER", description: "Number of bedrooms" },
      { name: "bathrooms", type: "DECIMAL", description: "Number of bathrooms" },
      { name: "year_built", type: "INTEGER", description: "Year built" },
      { name: "adjusted_price", type: "CURRENCY_AMOUNT", description: "Sale price after adjustments" },
      { name: "proximity_to_subject", type: "TEXT", description: "Distance or proximity to the subject property" },
    ],
  },
}

The adjusted price is what matters for valuation. Appraisers adjust comparable sale prices to account for differences — a comparable with a two-car garage gets a negative adjustment if the subject property has a one-car garage. The adjusted price reflects what the comparable would have sold for if it were identical to the subject property.

Having both the raw sale price and the adjusted price in structured form lets you verify the appraiser’s adjustments programmatically. If the adjustment between sale price and adjusted price seems disproportionate, that’s a flag for review.

Condition Assessment and Property Details

The condition ENUM maps the appraiser’s subjective assessment to a standardized scale. Appraisers use different terminology — “C3” on a URAR form, “Good” in a narrative report, “Above Average” in another format. The ENUM field normalizes these into your predefined categories.

For more detailed condition data, extend the schema with specific condition components:

{
  name: "condition_notes",
  type: "TEXTAREA",
  description: "Appraiser's notes on property condition, repairs needed, and maintenance status",
},
{
  name: "has_recent_renovations",
  type: "BOOLEAN",
  description: "Whether the property has had recent renovations or updates",
},
{
  name: "estimated_remaining_life_in_years",
  type: "INTEGER",
  description: "Estimated remaining economic life of the property in years",
},

The TEXTAREA field for condition notes captures the appraiser’s narrative commentary — things like “roof replaced in 2024, HVAC original to construction, kitchen updated with granite countertops.” This narrative is hard to extract with template parsing because every appraiser writes it differently. Schema-based extraction reads the meaning, not the format.

Key Field Types for Real Estate

  • ADDRESS — decomposes into components with ISO country codes. Works for the subject property and all comparable addresses.
  • CURRENCY_AMOUNT — extracts clean numeric values from prices regardless of formatting ($385,000 vs 385.000 vs 385,000.00).
  • DECIMAL — handles square footage, lot sizes, and other measurements with precision.
  • ARRAY — the comparable sales table comes out as structured rows, no matter how many comps are included.
  • ENUM — property type and condition map to your predefined categories.
  • DATE — normalizes appraisal dates and sale dates across formats.

Batch Processing for Portfolio Analysis

Processing appraisals for a real estate portfolio? Send up to 20 appraisal documents in a single batch request. The same schema extracts property data from every document — different appraisal firms, different formats, consistent structured output.

This is particularly useful for loan portfolios. A lender reviewing 500 properties in a portfolio has 500 appraisals from dozens of different firms, spanning several years of appraisal format changes. Manual data entry is not practical at that scale. Batch extraction with a consistent schema gives you a structured dataset for the entire portfolio in a fraction of the time.

Cross-Referencing Appraisal Data

Once you have structured appraisal data, cross-referencing becomes straightforward. Compare the appraised value against the comparable sale prices. Check if the price per square foot is consistent with the comparables. Verify that the property condition rating aligns with the year built and any noted renovations.

const pricePerSqFt = data.appraisedValue.value / data.livingAreaInSqFt.value;

const compPricesPerSqFt = data.comparableSales.value.map((comp) => {
  const compPrice = comp.at(1).value;
  const compSqFt = comp.at(3).value;

  return compPrice / compSqFt;
});

If the subject property’s price per square foot is significantly higher or lower than the comparables, it’s worth a closer look. Structured data makes these checks automatic rather than manual.

Get Started

Check the docs for the ADDRESS field reference and the full list of field types. The TypeScript and Python SDKs are available for server-side integration.

Sign up for a free account — no credit card required. Parse a sample appraisal and see how the schema handles your specific document formats.

Start building in minutes

Free trial included. No credit card required.