# Crexi Scraper (`scraptivo/crexi-scraper`) Actor

Collects Crexi.com commercial real estate listings for sale and lease from search queries or URLs. Returns price, property type, location, and optional listing details.

- **URL**: https://apify.com/scraptivo/crexi-scraper.md
- **Developed by:** [Scraptivo](https://apify.com/scraptivo) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.97 / 1,000 listings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

**Crexi Scraper** collects commercial real estate listings from [Crexi](https://www.crexi.com) and turns them into structured data for deal sourcing, market research, and broker outreach. Provide a city or keyword, a Crexi search or listing URL, run the Actor, and export price, property type, address, and listing IDs to JSON, CSV, Excel, or your preferred integration. Use it to monitor for-sale and for-lease inventory and automate recurring collection. Pricing starts at **$1.00 per 1,000 listings**, with optional listing details at **$2.00 per 1,000**.

### What can you automate with Crexi Scraper?

- **Build a CRE database** — Collect for-sale and for-lease listings with property specs, location, and images.
- **Filter by type and price** — Restrict results to Retail, Multifamily, Office, Industrial, Land, and other Crexi types.
- **Search by city or keyword** — Use queries such as `Houston` or `shopping center`, or paste a Crexi URL.
- **Enrich selected assets** — Turn on listing details for marketing description, investment highlights, gallery, and broker contacts.
- **Watch status changes** — Track On-Market, Auction, Highest & Best, and Call For Offers listings on a schedule.
- **Feed a deal pipeline** — Export JSON, CSV, or Excel, or push results through a webhook.

### Who is this scraper for?

| Team | Workflow |
|---|---|
| CRE investors and brokers | Sourcing sale and lease listings by city, type, and price. |
| Market researchers | Comparing asking strategies and listing activity across submarkets. |
| Analysts | Building structured property datasets for models and maps. |
| Outreach teams | Collecting broker names and contacts after a details run. |

### What data can you collect from Crexi?

| Data group | Example fields | How it helps |
|---|---|---|
| Listing identity | Listing ID, `propertyName`, URL, status | Deduplicate and reopen the asset. |
| Price and type | `askingPrice`, `propertyType`, `propertySubType`, document type | Screen sale vs lease inventory. |
| Location | Full address, city, state, ZIP, coordinates | Map assets and filter by market. |
| Specs | Building sqft, lot acres, year built, class | Compare physical attributes. |
| Details | Marketing description, investment highlights, gallery, broker contacts | Appear when **Scrape Listing Details** is enabled. |

Card-level name, price, type, city, and URL are returned on every listing. Marketing copy, full gallery, and broker phones appear only when details are enabled.

### How to use Crexi Scraper

1. Open the [Crexi Scraper](https://apify.com/scraptivo/crexi-scraper) on Apify.
2. Enter a search query such as `Houston`, or paste Crexi search or listing URLs.
3. Choose Sales or Lease, property types, an optional price range, and a `maxItems` limit.
4. Run the Actor and wait for listing records to appear in the dataset.
5. Export JSON, CSV, or Excel, or connect the dataset to your workflow.

```json
{
    "searchQueries": ["Houston"],
    "searchType": "Sales",
    "propertyTypes": ["Retail"],
    "maxItems": 20,
    "scrapeDetails": false,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": ["RESIDENTIAL"]
    }
}
```

### Example workflow

#### Watch Houston retail for sale every week

1. Schedule a Monday run with `searchQueries` = `["Houston"]`, `searchType` = `Sales`, and `propertyTypes` = `["Retail"]`.
2. Keep `scrapeDetails` off for a cheap card-level snapshot, then enable it on a shortlist.
3. Send new records to Google Sheets through a webhook.
4. Deduplicate user-side against the listing `id` or URL.

### Automate and integrate your results

- **Schedules** — CRE inventory changes slowly. Run **weekly** for most markets, or **daily** for auction and call-for-offers watches.
- **Webhooks** — Push completed datasets into Sheets, Slack, or a CRM.
- **Exports and API** — Download from the Apify Console or start a run from the API:

```shell
curl "https://api.apify.com/v2/acts/scraptivo~crexi-scraper/runs?token=YOUR-APIFY-TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "searchQueries": ["Houston"],
    "searchType": "Sales",
    "propertyTypes": ["Retail"],
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": ["RESIDENTIAL"]
    }
  }'
```

- **Deduplication** — The Actor appends results on every run. Use the listing `id` or URL as the stable key.

### Input reference

| Field | Type | Required | Default | What it controls |
|---|---|---:|---|---|
| `searchQueries` | Array of strings | No | — | Free-text terms such as city or property name. |
| `startUrls` | Array of URLs | No | — | Crexi search URLs or direct listing URLs. |
| `searchType` | String | No | `Sales` | `Sales` or `Lease`. Ignored for direct listing URLs. |
| `propertyTypes` | Array of strings | No | — | Retail, Multifamily, Office, Industrial, Hospitality, Mixed Use, Land, Self Storage, Mobile Home Park, Senior Living, Special Purpose, Note/Loan, Business for Sale. |
| `statuses` | Array of strings | No | — | On-Market, Auction, Highest & Best, Call For Offers (Sales). |
| `locations` | Array of strings | No | — | City names for the Crexi address filter. |
| `minPrice` / `maxPrice` | Integer | No | — | Asking price range in USD (Sales only). |
| `scrapeDetails` | Boolean | No | `false` | Fetch marketing copy, gallery, and broker contacts. Charges `listing-details`. |
| `maxConcurrency` | Integer | No | `5` | Parallel detail fetches (1–20). |
| `maxItems` | Integer | No | `0` | Maximum listings (`0` = unlimited). |
| `proxyConfiguration` | Proxy object | No | Apify proxy, RESIDENTIAL | Residential proxies are recommended. |

#### Do Start URLs keep their filters?

Yes. A Crexi search URL keeps the filters already in the link. `searchType` and constructed filters apply when you use `searchQueries` or the filter fields.

### Output example

Each dataset item is one listing:

```json
{
    "id": "sales-2623356",
    "url": "https://www.crexi.com/properties/2623356/HOUSTON-TX-77064",
    "propertyName": "17000 STATE HIGHWAY 249 HOUSTON TX 77064",
    "status": "Active",
    "propertyType": "Office, Retail",
    "propertySubType": "Medical Office, Storefront",
    "buildingSqft": 17000,
    "yearBuilt": 2026,
    "fullAddress": "17000 STATE HWY 249, HOUSTON, TX 77064",
    "city": "HOUSTON",
    "state": "TX",
    "detailsFetched": false
}
```

### How much does it cost to scrape Crexi?

The Actor uses pay-per-event pricing plus a small Actor-start event ($0.00005 per start, scaled by memory):

- **$1.00 / 1,000 listings** — a `dataset-item` event for every listing written to the dataset.
- **$2.00 / 1,000 listing details** — a `listing-details` event only when **Scrape Listing Details** is enabled.

A listing-only run of 1,000 properties costs **$1.00**. Enriching the same 1,000 listings with details costs **$3.00**. Volume discounts on Apify paid plans reduce the per-1,000 rate (for example **$0.97 per 1,000 listings** and **$1.70 per 1,000 details** at the Gold plan). Compute units consumed are deducted from your Apify plan.

### Reliability and responsible use

- **Proxy requirement** — Residential proxies are recommended. The default input uses the Apify RESIDENTIAL group.
- **Conditional fields** — Marketing description, investment highlights, full gallery, and broker contacts appear only when details are enabled.
- **Public listings** — The Actor collects publicly visible Crexi listing data.
- **Responsible use** — Only use the data in ways that comply with Crexi terms and applicable law.

### Frequently asked questions

#### Can I scrape Crexi listings by city and property type?

Yes. Set `searchQueries` or `locations` to a city and choose `propertyTypes` such as `Retail` or `Industrial`. Use `searchType` = `Sales` or `Lease`.

#### Can I schedule Crexi Scraper to run automatically?

Yes. Use the **Scheduler** tab in Apify Console. Weekly works for most markets.

#### What counts as one result?

Each listing saved to the dataset is one `dataset-item` event ($1.00 per 1,000). If details are enabled, each successful detail fetch also counts as a `listing-details` event ($2.00 per 1,000).

#### Why are some fields empty?

Broker contacts, marketing copy, and full galleries are collected only when **Scrape Listing Details** is enabled. Crexi also leaves some card fields empty.

#### How do I avoid duplicate records?

The Actor does not deduplicate across runs. Use the listing `id` or URL. `maxItems` caps a single run.

#### Do I need a proxy?

Residential proxies are recommended and are the default.

### Related Scraptivo automations

- [Realtor Scraper](https://apify.com/scraptivo/realtor-scraper) — residential listings from Realtor.com.
- [Realtor.com Agent Scraper](https://apify.com/scraptivo/realtor-agent-scraper) — agent records from Realtor.com.
- [BizBuySell Scraper](https://apify.com/scraptivo/bizbuysell-scraper) — businesses for sale.

### Support and custom workflows

Need a different field, source, or delivery workflow? Contact Scraptivo at scraptivo@gmail.com. Include the Actor name, sample URL, required fields, and expected volume so we can assess the request.

# Actor input Schema

## `searchQueries` (type: `array`):

Free-text search terms (city, keyword, property name, etc.). Combined with filters below. e.g. "Houston", "shopping center", "CVS".

## `startUrls` (type: `array`):

Crexi search or listing URLs. Search URLs (e.g. https://www.crexi.com/search?searchType=Sales\&propertyAttributes.type\_tree\_Retail=) apply pagination with filters from the URL. Listing URLs (e.g. https://www.crexi.com/properties/2024073/Rockport-TX-78382) scrape that property.

## `searchType` (type: `string`):

Listing marketplace to search. Used when searchQueries or filters are provided (ignored for direct listing URLs).

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

Filter by Crexi property type. Leave empty for all types.

## `statuses` (type: `array`):

Active listing statuses for Sales searches. Defaults to all active statuses when empty. For Auction-only, select Auction.

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

City names to include via Crexi address filter. e.g. "Chicago", "Los Angeles", "Houston".

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

Minimum asking price (Sales only). Leave empty for no minimum.

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

Maximum asking price (Sales only). Leave empty for no maximum.

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

When enabled, fetches full listing details (marketing description, investment highlights, full gallery, broker contacts) in parallel with rotated residential proxies. Charges an extra listing-details event per successful detail fetch. Disabled by default for faster, cheaper listing-only runs.

## `maxConcurrency` (type: `integer`):

How many listing-detail enrichments to run in parallel when scrapeDetails is enabled. Each in-flight listing rotates proxies per API call. e.g. 5.

## `maxItems` (type: `integer`):

Maximum number of listings to scrape (0 = unlimited)

## `proxyConfiguration` (type: `object`):

Proxy settings. Residential proxies are recommended for Crexi.

## Actor input object example

```json
{
  "searchQueries": [
    "Houston"
  ],
  "startUrls": [
    {
      "url": "https://www.crexi.com/search?propertyAttributes.type_tree_Retail=&searchType=Sales"
    }
  ],
  "searchType": "Sales",
  "propertyTypes": [
    "Retail"
  ],
  "statuses": [],
  "scrapeDetails": false,
  "maxConcurrency": 5,
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset containing scraped Crexi listings

## `runStats` (type: `string`):

Aggregate scrape statistics for this run

# 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 = {
    "searchQueries": [
        "Houston"
    ],
    "startUrls": [
        {
            "url": "https://www.crexi.com/search?propertyAttributes.type_tree_Retail=&searchType=Sales"
        }
    ],
    "propertyTypes": [
        "Retail"
    ],
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scraptivo/crexi-scraper").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 = {
    "searchQueries": ["Houston"],
    "startUrls": [{ "url": "https://www.crexi.com/search?propertyAttributes.type_tree_Retail=&searchType=Sales" }],
    "propertyTypes": ["Retail"],
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("scraptivo/crexi-scraper").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 '{
  "searchQueries": [
    "Houston"
  ],
  "startUrls": [
    {
      "url": "https://www.crexi.com/search?propertyAttributes.type_tree_Retail=&searchType=Sales"
    }
  ],
  "propertyTypes": [
    "Retail"
  ],
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call scraptivo/crexi-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scraptivo/crexi-scraper"
        }
    }
}

```

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/0iXB6B4hL6DlgZfan/builds/ashGdbv8VJtUnufJ5/openapi.json
