# Crexi Commercial Property Listings & Pricing Extractor (`dataspryva/crexi-commercial-property-listings-and-pricing`) Actor

Collects active commercial real estate listings from Crexi across any US state and 14 property types, with asking price, square footage, location, and brokerage details.

- **URL**: https://apify.com/dataspryva/crexi-commercial-property-listings-and-pricing.md
- **Developed by:** [Dataspryva](https://apify.com/dataspryva) (community)
- **Categories:** Real estate, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Crexi Commercial Property Listings & Pricing Extractor

Crexi is one of the largest US marketplaces for commercial real estate. This actor reads Crexi's own public listing APIs and returns for-sale, for-lease and auction properties as clean, structured rows — asking price, cap rate, NOI, building size, year built, lot size, broker contacts, photo galleries and coordinates. No account, cookies or proxy setup are required.

### What this actor does

- **Three marketplaces in one actor:** for-sale listings, for-lease listings and live auctions, with the filters each one actually supports.
- **Full filter surface:** keywords, states, cities, counties, ZIP codes, 14 property categories, 50 subtypes, building class, asking price, price per square foot, cap rate, building size, lease rate, and Opportunity Zone listings.
- **Handles Crexi's result window for you.** Crexi's API only returns 1,500 rows per filter combination. When you ask for more, the actor automatically splits the search into price-range partitions and merges the results, deduplicated.
- **Direct URL mode:** paste any Crexi property link or ID — for-sale or for-lease — and the actor fetches exactly those records.
- **Optional enrichment:** one toggle adds full broker contacts (name, brokerage website, license, profile), high-resolution gallery photos, investment highlights, the marketing write-up and published fact-sheet values.
- **Optional comps:** attach up to six similar nearby listings to each record.
- Fields Crexi does not publish for a listing (for example an undisclosed price) are omitted from that record instead of being written as blank or null.

### Output per listing

- `property_id`, `name`, `property_url`, `record_type: "property"` (property-record rows use `record_type: "property_record"`)
- `transaction_type` — `sale` or `lease`; `is_auction` and the auction block for auction listings
- `property_type` (asset class), `subtypes[]`
- `address`, `city`, `county`, `state`, `zip_code`, `latitude`, `longitude`
- `price` (formatted) and `price_usd` (number), `price_per_sqft`, `price_per_acre`
- `square_footage` (formatted) and `building_sqft` (number), `lot_acres`
- `cap_rate`, `net_operating_income` (formatted) and `noi_usd` (number)
- `year_built`, `year_renovated`, `class`, `tenancy`, `units`, `stories`
- `brokerage`, `broker_names[]` — and with enrichment, `brokers[]` with profile, website, license, photo, **phone and email**, plus `broker_phones[]`/`broker_emails[]` and `broker_of_record` (name, license, phone when Crexi publishes it)
- `listing_status`, `investment_type`, `offers_due_on`, `is_opportunity_zone`
- Auction rows: `is_auction`, `auction_starting_bid_usd`, `auction_minimum_bid_usd`, `auction_starts_on`, `auction_ends_on`; with enrichment also `auction_status`, `auction_bid_increment_usd`, `auction_reserve_met`, `auction_marketing_starts_on`, `auction_earnest_deposit_usd`/`auction_earnest_deposit_percent`, `auction_deposit_option`, `auction_escrow_period_days`, `auction_participation_deposit_usd`, `auctioneer`, `auction_transaction_fee_percent`, `auction_minimum_fee_usd`, `auction_registered_bidders`, `auction_approved_bidders`, `auction_page_views`
- `has_om`, `has_flyer`, `has_video`, `has_virtual_tour`
- `activated_on`, `updated_on`, `days_on_market`
- `description`; with enrichment also `marketing_description`, `investment_highlights[]`, `details`
- `images[]` (all gallery photos), `image_count`
- `source`, `scraped_at`
- Lease listings add `lease_type`, `rate_type`, `lease_rate_per_sqft_annual`, `lease_rate_monthly_total`, `rentable_sqft_min`, `rentable_sqft_max`, `suites`, `vacant_suites`
- With similar properties enabled: `similar_properties[]` — id, name, price and link for each comp (Crexi returns up to 500 per listing)

#### Output per property record (property-record URL input)

- `property_id`, `name`, `property_url` (`https://www.crexi.com/property-records/...`), `record_type: "property_record"`
- `apn`, `regrid_path` — parcel identifiers
- `address`, `city`, `county`, `state`, `zip_code`, `latitude`, `longitude`
- `property_type`, `subtypes[]`, `class`, `building_sqft`, `buildings`, `units`, `lot_acres`, `lot_sqft`, `year_built`, `tenancy`
- `days_on_market`, `sale_transaction_type`, `is_sales_comp`, `is_lease_comp`, `sales_comp_type`, `lease_comp_type`, `is_broker_reported_sales_comp`
- `broker_names[]`, `description`, `images[]`, `image_count`, `activated_on`, `updated_on`
- `related_sale_listing_ids[]` / `related_lease_listing_ids[]` when Crexi links the record to marketplace listings

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `propertyUrls` | Array | – | Crexi property links, `/lease/properties/...` links, bare IDs, or `property-records/...` links to fetch exact rows. A Crexi search URL is also accepted and its filters are reused. When set, the filter fields below are skipped. |
| `transactionTypes` | Select (multi) | – | `sale`, `lease` or `auction`. Empty means for-sale only. |
| `searchTerms` | Array | – | Keywords matched against listing names, descriptions and addresses. |
| `propertyTypes` | Select (multi) | – | 14 commercial categories. Empty searches every type. |
| `subtypes` | Select (multi) | – | 50 subtypes such as Shopping Center, Medical Office, Warehouse. Some subtypes exist only for sale or only for lease. |
| `locations` | Select (multi) | – | US states by two-letter code or full name. Empty searches nationwide. |
| `cities` | Array | – | City names, e.g. `Austin`. |
| `counties` | Array | – | County names as Crexi writes them, e.g. `Travis County`. |
| `zipCodes` | Array | – | US ZIP codes, e.g. `78701`. |
| `minPrice` / `maxPrice` | Integer | – | Asking-price range in USD (sale and auction listings). |
| `minPricePerSqft` / `maxPricePerSqft` | Number | – | Price-per-square-foot range (sale listings). |
| `minCapRate` / `maxCapRate` | Number | – | Cap-rate range in percent (sale listings with a published cap rate). |
| `minSquareFootage` / `maxSquareFootage` | Integer | – | Building-size range in square feet. |
| `minRatePerSqftAnnual` / `maxRatePerSqftAnnual` | Number | – | Annual lease-rate range per square foot (lease listings). |
| `buildingClasses` | Select (multi) | – | `A`, `B` or `C`. |
| `opportunityZoneOnly` | Boolean | `false` | Only listings in designated Opportunity Zones. |
| `includeUnpriced` | Boolean | `true` | Keep listings without a public asking price. |
| `sortBy` | Select | `Rank` | Recommended, price, cap rate, NOI, recently updated, recently listed or newest. |
| `sortDirection` | Select | `Descending` | Descending or ascending. Lease listings always sort by Crexi's recommended order and skip this. |
| `scrapeDetails` | Boolean | `false` | Add broker phone/email contacts, high-resolution photos, highlights, marketing text, fact-sheet values and full auction details. |
| `includeSimilarProperties` | Boolean | `false` | Attach up to 6 similar nearby listings to each record. |
| `maxProperties` | Integer | `100` | Stop after this many listings (1–100,000). The daily sample uses `5`. |

#### Example: multifamily deals in Texas, $2M–$10M, with details

```json
{
  "transactionTypes": ["sale"],
  "propertyTypes": ["Multifamily"],
  "locations": ["TX"],
  "minPrice": 2000000,
  "maxPrice": 10000000,
  "scrapeDetails": true,
  "maxProperties": 200
}
```

#### Example: retail and office space for lease in Austin

```json
{
  "transactionTypes": ["lease"],
  "cities": ["Austin"],
  "zipCodes": ["78701", "78702"],
  "maxProperties": 100
}
```

#### Example: live auctions over $1M

```json
{
  "transactionTypes": ["auction"],
  "minPrice": 1000000,
  "maxProperties": 50
}
```

#### Example: fetch specific listings

```json
{
  "propertyUrls": [
    "https://www.crexi.com/properties/2492041/pennsylvania-former-pittsburgh-hospital",
    "https://www.crexi.com/lease/properties/28945/california-french-valley-village-center"
  ],
  "scrapeDetails": true
}
```

### Use cases

- **Acquisition sourcing** — build lists of for-sale and for-lease assets that match a buy box of state, city, ZIP, type, size, price and cap rate.
- **Market research** — compare inventory and asking prices across metros, categories and lease versus sale markets.
- **Broker outreach** — collect brokerage and broker names, license numbers and profile links tied to active listings.
- **Underwriting support** — pull NOI, cap rate, year built, lot size and fact-sheet values for first-pass screening.
- **Auction monitoring** — track live auctions with starting bids and start/end dates before offers close.

### FAQ

**Do I need a Crexi account, cookies or a proxy?**
No. The actor connects to Crexi automatically; there is nothing to configure.

**Why did I get exactly 1,500 rows for a broad search?**
Crexi's API returns at most 1,500 rows per filter combination. The actor works around this by splitting large searches into price-range partitions and merging the results; a nationwide request for more than 1,500 rows is collected partition by partition. If a single indivisible slice still exceeds 1,500, the run's status message tells you the site's total and suggests narrowing filters.

**Why is `price` missing on some listings?**
Some sellers publish a listing without an asking price. Those rows still contain everything else; with `includeUnpriced` off they are excluded entirely — and an active price filter always requires a published price.

**Why are `cap_rate` or `net_operating_income` missing on some rows?**
Crexi only exposes those figures when the listing publishes them. When they are absent from the source, the fields are omitted rather than estimated.

**What does `scrapeDetails` add?**
Each listing's detail data: broker phone and email contacts (with brokerage website, license number and profile link), plus `broker_phones[]`/`broker_emails[]` roll-ups; the full gallery in high resolution; investment highlights; the marketing description; published fact-sheet values such as zoning and ownership; the lease rate block for lease listings; and full auction details (deposits, bid increment, reserve status, bidder counts). It takes longer to run, so it is off by default.

**Does this include sold or off-market properties?**
Crexi's sold prices and sale dates sit behind its paid Intelligence product and are never published anonymously, so the actor cannot return them. It does cover active for-sale, for-lease and auction listings, and it can fetch public property records (parcel data such as APN, lot and building size, class and comp flags) when you paste a `crexi.com/property-records/...` URL into `propertyUrls`.

**Can I filter by year built, NOI or occupancy?**
Crexi only filters cap rate server-side (the `minCapRate`/`maxCapRate` inputs). Year built and NOI are returned on each record when published but cannot be filtered before download; occupancy is masked for anonymous users on sale listings (for-lease rows expose `vacant_suites`).

**Can I mix sale and lease results in one run?**
Yes — select both in `transactionTypes` and the actor searches each marketplace and combines the rows into one deduplicated dataset. Crexi's for-sale and for-lease marketplaces use separate ID spaces, so the same `property_id` can appear once per marketplace; `transaction_type` and `property_url` tell the two records apart.

**How fresh is the data?**
Every run queries Crexi live, so results reflect the marketplace at the moment the run starts.

**Is this actor affiliated with Crexi?**
No. It is an independent tool that reads Crexi's public listing pages and APIs and is not operated by or affiliated with Crexi.

# Actor input Schema

## `propertyUrls` (type: `array`):

Paste Crexi property links or IDs (e.g. https://www.crexi.com/properties/123456/name, /lease/properties/987/name, a bare ID, or a property-record link) to fetch those exact listings. A Crexi search URL (https://www.crexi.com/search/...) is also accepted and its filters are reused. Leave empty to search by the filters below.

## `transactionTypes` (type: `array`):

Which Crexi marketplaces to search. Empty = for-sale listings only.

## `searchTerms` (type: `array`):

Free-text keywords matched against listing names, descriptions and addresses (e.g. warehouse, medical office).

## `propertyTypes` (type: `array`):

One or more commercial property categories. Empty searches every type.

## `subtypes` (type: `array`):

Narrow to specific subtypes (e.g. Shopping Center, Medical Office, Warehouse). Note: some subtypes exist only for sale or only for lease listings.

## `locations` (type: `array`):

US states to search, by two-letter code or full name. Each state is searched and combined. Empty searches nationwide.

## `cities` (type: `array`):

City names to filter by (e.g. Austin). Works alongside or instead of states.

## `counties` (type: `array`):

County names to filter by, including the word County where Crexi uses it (e.g. Travis County).

## `zipCodes` (type: `array`):

US ZIP codes to filter by (e.g. 78701).

## `minPrice` (type: `integer`):

Only return listings asking at least this much. Sale and auction listings only.

## `maxPrice` (type: `integer`):

Only return listings asking at most this much. Sale and auction listings only.

## `minPricePerSqft` (type: `number`):

Only return sale listings priced at or above this per square foot.

## `maxPricePerSqft` (type: `number`):

Only return sale listings priced at or below this per square foot.

## `minCapRate` (type: `number`):

Only return sale listings with a published cap rate at or above this percentage.

## `maxCapRate` (type: `number`):

Only return sale listings with a published cap rate at or below this percentage.

## `minSquareFootage` (type: `integer`):

Only return listings whose building is at least this large.

## `maxSquareFootage` (type: `integer`):

Only return listings whose building is at most this large.

## `minRatePerSqftAnnual` (type: `number`):

For-lease listings only: minimum annual rate per square foot.

## `maxRatePerSqftAnnual` (type: `number`):

For-lease listings only: maximum annual rate per square foot.

## `buildingClasses` (type: `array`):

Filter by commercial building class. Empty includes all classes.

## `opportunityZoneOnly` (type: `boolean`):

Only return sale listings located in a designated Opportunity Zone.

## `includeUnpriced` (type: `boolean`):

Include sale and auction listings Crexi shows without a public asking price (auctions, call for offers).

## `sortBy` (type: `string`):

Order of results within each search.

## `sortDirection` (type: `string`):

Ascending or descending order for the sort chosen above.

## `scrapeDetails` (type: `boolean`):

Fetch each listing's detail data: broker contacts (phone and email), the broker of record when published, the full photo gallery in high resolution, investment highlights, the marketing description, published fact-sheet values, and full auction details for auction listings. Adds a few requests per listing.

## `includeSimilarProperties` (type: `boolean`):

Add up to 6 similar nearby listings (comps) to each record.

## `maxProperties` (type: `integer`):

Stop once this many listings have been collected. Crexi returns at most 1,500 rows per filter combination; larger requests are automatically split into price-range partitions.

## Actor input object example

```json
{
  "propertyUrls": [],
  "transactionTypes": [],
  "searchTerms": [],
  "propertyTypes": [],
  "subtypes": [],
  "locations": [],
  "cities": [],
  "counties": [],
  "zipCodes": [],
  "buildingClasses": [],
  "opportunityZoneOnly": false,
  "includeUnpriced": true,
  "sortBy": "Rank",
  "sortDirection": "Descending",
  "scrapeDetails": false,
  "includeSimilarProperties": false,
  "maxProperties": 5
}
```

# Actor output Schema

## `listings` (type: `string`):

Dataset containing all scraped Crexi commercial property listings.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "propertyUrls": [],
    "searchTerms": [],
    "cities": [],
    "counties": [],
    "zipCodes": [],
    "opportunityZoneOnly": false,
    "includeUnpriced": true,
    "sortBy": "Rank",
    "sortDirection": "Descending",
    "scrapeDetails": false,
    "includeSimilarProperties": false,
    "maxProperties": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("dataspryva/crexi-commercial-property-listings-and-pricing").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "propertyUrls": [],
    "searchTerms": [],
    "cities": [],
    "counties": [],
    "zipCodes": [],
    "opportunityZoneOnly": False,
    "includeUnpriced": True,
    "sortBy": "Rank",
    "sortDirection": "Descending",
    "scrapeDetails": False,
    "includeSimilarProperties": False,
    "maxProperties": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("dataspryva/crexi-commercial-property-listings-and-pricing").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "propertyUrls": [],
  "searchTerms": [],
  "cities": [],
  "counties": [],
  "zipCodes": [],
  "opportunityZoneOnly": false,
  "includeUnpriced": true,
  "sortBy": "Rank",
  "sortDirection": "Descending",
  "scrapeDetails": false,
  "includeSimilarProperties": false,
  "maxProperties": 5
}' |
apify call dataspryva/crexi-commercial-property-listings-and-pricing --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dataspryva/crexi-commercial-property-listings-and-pricing"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/dZkzHEvhJd9SJS0qj/builds/SreNgxMszQEyRWGfu/openapi.json
