Crexi APIcrexi.com ↗
Search and retrieve commercial real estate listings from Crexi.com. Get property details, cap rates, NOI, pricing, broker info, and more via 3 endpoints.
What is the Crexi API?
The Crexi API gives developers structured access to commercial real estate listings across 3 endpoints, covering asking price, cap rate, NOI, broker contact details, and full property descriptions. Use search_properties to query listings by type and price range with paginated results, get_property_detail to pull full investment and occupancy data for a single property, or get_all_listings to collect every matching listing without managing pagination yourself.
curl -X GET 'https://api.parse.bot/scraper/ac745241-4ec0-46fa-8f98-e9ede92c503a/search_properties?page=1&max_price=5000000&min_price=100000&page_size=5&sort_order=rank&property_type=mobile_home_park&sort_direction=Ascending' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace crexi-com-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: Crexi SDK — search CRE listings, drill into details, bulk collect."""
from parse_apis.crexi_commercial_real_estate_listings_api import (
Crexi, PropertyType, Sort, SortDirection, PropertyNotFound
)
client = Crexi()
# Search for multifamily properties sorted by price, capped at 5 results.
for listing in client.propertysummaries.search(
property_type=PropertyType.MULTIFAMILY,
sort_order=Sort.PRICE,
sort_direction=SortDirection.ASCENDING,
max_price=5000000,
limit=5,
):
print(listing.name, listing.asking_price, listing.state)
# Drill into the first result's full details (separate fetch).
summary = client.propertysummaries.search(
property_type=PropertyType.RETAIL, limit=1
).first()
if summary:
detail = summary.details()
print(detail.name, detail.occupancy, detail.marketing_description)
for broker in detail.brokers:
print(broker.first_name, broker.last_name, broker.brokerage_name)
# Typed error handling for a missing property.
try:
bad_summary = client.propertysummaries.search(
property_type=PropertyType.OFFICE, limit=1
).first()
if bad_summary:
bad_summary.details()
except PropertyNotFound as exc:
print(f"Property gone: {exc.property_id}")
# Bulk collect mobile home parks (limited to 3 items).
for park in client.propertysummaries.collect(
property_type=PropertyType.MOBILE_HOME_PARK,
max_results=3,
limit=3,
):
print(park.name, park.cap_rate, park.brokerage_name)
print("exercised: propertysummaries.search / .collect / summary.details / PropertyNotFound")
Search for commercial real estate properties by type with pagination. Returns listing summaries including price, cap rate, NOI, location, and broker info. Supports sorting by relevance, price, cap rate, or listing date. Server-side filtering is limited to property type and price range; finer filters require client-side post-processing. Each PropertySummary exposes a .details() navigation to the full Property.
| Param | Type | Description |
|---|---|---|
| page | integer | Page number (1-based) |
| max_price | number | Maximum asking price filter in USD |
| min_price | number | Minimum asking price filter in USD |
| page_size | integer | Results per page (max 60) |
| sort_order | string | Sort field |
| property_type | string | Property type to filter by |
| sort_direction | string | Sort direction |
{
"type": "object",
"fields": {
"page": "integer, current page number",
"listings": "array of listing summary objects with id, name, address, city, state, zip, asking_price, cap_rate, noi, property_types, brokerage_name, and more",
"page_size": "integer, results per page",
"total_count": "integer, total number of matching listings",
"total_pages": "integer, total number of pages"
},
"sample": {
"data": {
"page": 1,
"listings": [
{
"id": 2492681,
"noi": null,
"url": "https://www.crexi.com/properties/2492681",
"zip": "60615",
"city": "Chicago",
"name": "8-Unit Apartment Building",
"state": "IL",
"county": "Cook County",
"has_om": true,
"status": "Auction",
"address": "211-213 E 48th St, Chicago, Cook County, IL 60615",
"cap_rate": null,
"latitude": 41.8073302,
"has_flyer": false,
"has_video": true,
"longitude": -87.6205852,
"occupancy": null,
"is_auction": true,
"state_name": "Illinois",
"updated_on": "2026-06-10T20:22:45Z",
"year_built": null,
"broker_name": null,
"building_sf": 9900,
"description": "VALUE-ADD MULTIFAMILY OPPORTUNITY",
"activated_on": "2026-05-22T18:45:17Z",
"asking_price": 100000,
"price_per_sf": 10.1,
"offers_due_on": "2026-07-15T16:00:00Z",
"thumbnail_url": "https://images.crexi.com/assets/2492681/773961044ffe4075b2b7b322361ae6af_716x444.jpg",
"brokerage_name": "Colliers - Chicago Downtown, Illinois",
"lot_size_acres": 0.12,
"price_per_acre": "$833,333.33/Acre",
"price_per_unit": null,
"property_types": [
"Multifamily"
],
"number_of_units": 8,
"is_in_opportunity_zone": true
}
],
"page_size": 5,
"total_count": 29144,
"total_pages": 5829
},
"status": "success"
}
}About the Crexi API
What the API Returns
The search_properties endpoint returns paginated listing summaries filtered by property_type and price range (min_price / max_price). Each result includes id, name, address, city, state, zip, asking_price, cap_rate, noi, property_types, and brokerage_name. You can sort results by relevance, price, cap rate, or listing date using sort_order and sort_direction, and control page size up to 60 results per request. Note that server-side filtering is limited to property type and price — additional filtering must be applied client-side.
Property Detail
get_property_detail accepts a numeric property_id from search results and returns a single property record. Beyond the summary fields, the response includes status, a brokers array with each broker's name and brokerage, a details object containing human-readable key-value pairs covering occupancy, investment type, and loan information, plus a full marketing description. This endpoint is the right tool when you need the full picture for a specific listing rather than a summary across many.
Bulk Retrieval
get_all_listings handles automatic pagination internally, iterating through pages until either max_results is reached or the full result set is collected. It returns the same listing shape as search_properties plus a complete boolean indicating whether all matching listings were fetched, a fetched_count, and a total_count. An optional delay parameter controls the interval between page requests. Use this endpoint when you need to build a local dataset without writing pagination loops.
The Crexi API is a managed, monitored endpoint for crexi.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when crexi.com changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official crexi.com API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Screen commercial investment properties by cap rate and NOI across a specific property type
- Build a market survey of asking prices for retail or industrial properties in a target region
- Aggregate broker contact data from listings to identify active CRE brokerages in a market
- Monitor new listings by sorting on listing date and comparing total_count over time
- Pull full property details including occupancy and loan terms for underwriting workflows
- Compile a bulk dataset of all listings matching a price range for comparative market analysis
- Enrich an internal CRE database with standardized address and property type fields from Crexi
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does Crexi have an official developer API?+
What filtering options does search_properties support server-side?+
property_type and price range via min_price and max_price. Fields like city, state, occupancy, or investment type are returned in the response but are not available as query filters — you would need to apply those filters on the results after retrieval.Does get_property_detail return the broker's phone number or email address?+
brokers array in get_property_detail returns id, first_name, last_name, and brokerage_name. Direct contact fields such as phone numbers or email addresses are not currently included in the response. The API covers listing-level broker identity data. You can fork it on Parse and revise to add those fields if they become accessible.Is there a way to filter listings by geographic area such as city or state?+
search_properties and get_all_listings endpoints accept property_type and price range filters only. City, state, and zip are returned on each listing object, so geo-filtering can be applied client-side after fetching. You can fork the API on Parse and revise it to add a location-based filter endpoint.How does get_all_listings differ from calling search_properties repeatedly?+
get_all_listings handles pagination internally and returns a single consolidated array of listing objects along with a complete boolean, fetched_count, and total_count. It also accepts a delay parameter to space out requests. search_properties returns one page at a time and requires you to manage page incrementing and termination logic yourself.