Guides

How to Scrape Crexi Commercial Real Estate Listings

Crexi is one of the largest US commercial real estate marketplaces, which makes it a rich public source of CRE data: property, address, asking price, size, and broker across sale and lease. This guide covers what a listing holds, where the data lives, the challenges of collecting it cleanly, and how to turn it into a CRE feed. The worked example uses a real Crexi listing.

DADataScrape TeamSeptember 2, 2026Updated September 28, 20265 min read

What data a Crexi listing holds

Each listing carries the property and the deal. On a real listing it read: 11 Homesites in Raymondskill Creek Subdivision, a Land listing with a Residential subtype, at Skyview Ln, Milford, PA 18337 in Pike County, priced at 250,000 dollars total, which works out to about 5,633 dollars per acre, listed for sale and brokered by Kristee Cassimore. Lease listings carry a rent and often a cap rate instead of a total. The property, address, price, type, and broker are the fields that matter, and each listing carries a stable id you deduplicate on.

Where the data actually lives

Crexi serves its search results from a clean public JSON API, api.crexi.com/universal-search/v2/search, which returns an items array where each object carries the property name, the property type and subtype, a price object with the total and the per-acre or per-square-foot figure, a full address with city, state, zip, county, and coordinates, the broker, and a documentType that marks the listing as Sales or Lease. Reading that JSON is far cleaner than parsing the rendered cards, since it hands you every field as structured data.

Skip the build, get the feed

Send us your Crexi target and we will scrape a real sample and send it back, no signup.

Get a free sample

The practical challenges

Crexi mixes sale and lease listings in one feed, so you split on the documentType, and price is expressed as a total, a per-acre, or a per-square-foot figure depending on the asset, so normalising it is part of the job. Property types and subtypes vary widely across land, office, retail, industrial, and multifamily. Access is defended, so automated requests need the right behaviour, and the same listing can appear across searches, so deduplication on the listing id matters. A scraper that works today can break after an API change.

Turning it into a CRE feed

For commercial real estate work you want one row per listing id, captured per market and property type, keeping the property, address, asking price, size, type, and broker. Refresh on a schedule so you catch new listings and price changes, and store each run with a date so you can see how long a listing sits and how asking prices move, which is often the intelligence that matters more than a single snapshot.

Build it yourself or have it delivered

For one market, a careful session against the search API can get you a sample. At scale the access handling, the paging, the price normalisation, and the upkeep turn it into a standing maintenance job. A done-for-you feed is usually cheaper than the maintenance once you track several markets. You tell us the markets and property types, and we deliver a clean CRE feed keyed on the listing id and keep it running.

Where each field lives in the search JSON

Crexi's search response is an items array of clean objects, so knowing the keys is what makes a parse reliable. Each item carries propertyName, a propertyAttributes block with the type and subType (for example Land and Residential), a propertyPrice object with total and a perAcre or perSquareFoot figure, an address list whose first entry holds fullAddress, city, stateCode, zip, county, and a lat/lon location, a brokers list whose first entry holds the broker name, and a documentType that reads Sales or Lease. The item id is the stable key you deduplicate on across runs. Because price arrives as a total or a per-unit figure depending on the asset, normalising against the numeric propertyPrice fields rather than a display string is what keeps the numbers comparable across sale and lease.

Step by step: reading a Crexi search

Crexi serves its search results from a clean public JSON API that its own frontend calls, so the cleanest read is that response. Here it is on a real listing, which came back as a structured object with price, address, type, and broker.

python
import requests

# Crexi's frontend loads listings from this public JSON search API.
url = "https://api.crexi.com/universal-search/v2/search"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
payload = {"searchText": "Austin, TX"}  # plus the site's own search filters

for it in requests.post(url, json=payload, headers=headers).json()["items"]:
    print(it["propertyName"], it["documentType"],
          it["propertyPrice"]["total"], it["address"][0]["fullAddress"])
Property11 Homesites in Raymondskill Creek Subdivision
TypeLand (Residential)
Listing typeSale
Price$250,000 ($5,633 / acre)
AddressSkyview Ln, Milford, PA 18337 (Pike County)
BrokerKristee Cassimore

A sample of the clean data we deliver for one product.

The response is clean and structured. The work is that Crexi mixes sale and lease listings, so you split on the documentType, price comes as a total, a per-acre, or a per-square-foot figure that needs normalising, and access is defended so requests need the right behaviour. Handling that at scale, deduplicating on the listing id, and keeping it working as the API changes is the real job. We run it and deliver a clean CRE feed keyed on the listing id.

Fields worth capturing from Crexi

  • Property name
  • Listing type (sale / lease)
  • Asking price
  • Price per acre / SF
  • Property type / subtype
  • Full address
  • City / state / ZIP
  • County
  • Broker name
  • Coordinates
  • Listing ID

Frequently asked questions

Want a Crexi feed without the build?

Send us the products or pages you need, and we will deliver a clean feed and maintain it. Start with a free sample.

Get a Free Sample