Crexi Scraper
Pricing
from $0.97 / 1,000 listings
Crexi Scraper
Crexi commercial real estate dataset for sale and lease listings, including prices, property types, locations, and optional listing details with broker contacts.
Pricing
from $0.97 / 1,000 listings
Rating
0.0
(0)
Developer
Farhan Ali
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Crexi Scraper creates a structured dataset of commercial real estate listings collected from Crexi, the US commercial marketplace. Each dataset item represents one Crexi listing and can include identifiers, asking price, property type and size, address, coordinates, status, images, and brokers, with optional marketing copy, financials, gallery URLs, and broker contacts. Query the source with searchQueries, Crexi search or listing startUrls, and filters for sale versus lease, property type, status, city, and price. Control the result limit with maxItems, and retrieve records through the Apify Dataset API or export them as JSON, CSV, Excel, or other supported formats.
Dataset at a glance
| Property | Value |
|---|---|
| Source | crexi.com (US commercial real estate marketplace) |
| Record unit | One Crexi commercial listing |
| Input methods | Search terms (searchQueries) or Crexi search/listing URLs (startUrls), plus filters |
| Main identifiers | id, url |
| Delivery | Apify Dataset and API |
| Export formats | JSON, CSV, Excel, XML, HTML (Apify dataset exports) |
| Update model | Fresh records per Actor run |
| Pricing | $1.00 per 1,000 listings; +$2.00 per 1,000 listing details; $0.00005 Actor start per run |
Coverage and available records
The Actor collects publicly listed commercial properties from Crexi.
- Search-based: Pass free-text terms in
searchQueries(city, keyword, or property name, for exampleHoustonorshopping center). Combine them withsearchType,propertyTypes,statuses,locations,minPrice, andmaxPrice. Filters alone can start a marketplace search when no queries or URLs are set. - URL-based: Pass Crexi search URLs or listing URLs in
startUrls. Search URLs are paginated using the filters in the URL. Listing URLs collect that single property.
Listing-level records are always collected. Detail fields (marketingDescription, investmentHighlights, details, brokerDetails, imageUrls, netOperatingIncome, capRatePercent) are returned only when scrapeDetails is enabled and the listing exposes them.
searchType selects Sales or Lease (default Sales). searchType, statuses, minPrice, and maxPrice apply to search runs and are ignored for direct listing URLs. Price filters apply to Sales searches only. An empty statuses list uses all active Sales statuses: On-Market, Auction, Highest & Best, and Call For Offers. An empty propertyTypes list includes all supported types. maxItems caps listings (0 = unlimited, the default; the input form prefills 20).
Known exclusions: login-gated Crexi content is not collected; each run captures listing state at run time (no historical snapshots).
Data dictionary
Field names match dataset JSON properties exactly. Fields marked conditional appear only when scrapeDetails is enabled and the listing exposes the value. Unpublished fields may be omitted or null.
Listing-level fields
| Field | Type | Nullable | Description | Example |
|---|---|---|---|---|
id | string | No | Crexi listing identifier; best stable deduplication key | sales-2623356 |
url | string | No | Public listing URL | https://www.crexi.com/properties/2623356/HOUSTON-TX-77064 |
propertyName | string | Yes | Listing title | 17000 STATE HIGHWAY 249 HOUSTON TX 77064 |
description | string | Yes | Short search-result summary | Brand new 17,000 SF 2-story freestanding retail building on SH 249 |
status | string | Yes | Listing status text | Active |
propertyType | string | Yes | Type or comma-separated types | Office, Retail |
propertySubType | string | Yes | Subtype or comma-separated subtypes | Medical Office, Storefront |
askingPrice | number | Yes | Asking price in USD when priced | — |
buildingSqft | number | Yes | Building area in square feet | 17000 |
lotSizeAcre | number | Yes | Lot size in acres | 11 |
yearBuilt | number | Yes | Year built | 2026 |
classType | string | Yes | Building class | A |
fullAddress | string | Yes | Full street address | 17000 STATE HWY 249, HOUSTON, TX 77064 |
city | string | Yes | City | HOUSTON |
state | string | Yes | State code | TX |
zip | string | Yes | ZIP code | 77064 |
county | string | Yes | County | HARRIS |
neighborhood | string | Yes | Neighborhood when listed | Willowbrook |
latitude | number | Yes | Map latitude | 29.9536066 |
longitude | number | Yes | Map longitude | -95.5397775 |
documentType | string | Yes | Sales or Lease | Sales |
sourceQuery | string | Yes | searchQueries term; absent for listing-URL seeds | Houston |
detailsFetched | boolean | No | Whether listing-detail fields were fetched | true |
imageCount | number | Yes | Number of listing images | 17 |
thumbnailUrl | string | Yes | Primary thumbnail URL | — |
brokers | object[] | Yes | Search-card brokers: {name, brokerage} | See example record |
id is the recommended deduplication key. url is a reasonable secondary key.
Listing detail fields (conditional — scrapeDetails)
| Field | Type | Nullable | Description | Example |
|---|---|---|---|---|
marketingDescription | string | Yes | Full marketing description | Long-form listing copy |
investmentHighlights | string | Yes | Investment highlights text | Long-form highlight copy |
details | object | Yes | Source key-value facts; keys vary by listing | See example record |
brokerDetails | object[] | Yes | Broker contacts from the listing | Name, brokerage, and contact fields when present |
imageUrls | string[] | Yes | Gallery image URLs | Array of image URLs |
netOperatingIncome | number | Yes | NOI when the listing publishes it | — |
capRatePercent | number | Yes | Cap rate percent when published | — |
The details object is a source-provided map of listing facts (for example Property Type, Investment Type, Tenancy, APN). Keys are not a fixed schema.
Example dataset record
Real record from the test input below (searchQueries: ["Houston"], searchType: Sales, propertyTypes: ["Retail"], scrapeDetails: true, maxItems: 10). Long marketing text and image URL arrays are omitted here; they appear when the listing publishes them.
{"id": "sales-2623356","url": "https://www.crexi.com/properties/2623356/HOUSTON-TX-77064","propertyName": "17000 STATE HIGHWAY 249 HOUSTON TX 77064","description": "Brand new 17,000 SF 2-story freestanding retail building on SH 249","status": "Active","propertyType": "Office, Retail","propertySubType": "Medical Office, Storefront","buildingSqft": 17000,"classType": "A","yearBuilt": 2026,"fullAddress": "17000 STATE HWY 249, HOUSTON, TX 77064","city": "HOUSTON","state": "TX","zip": "77064","county": "HARRIS","neighborhood": "Willowbrook","latitude": 29.9536066,"longitude": -95.5397775,"imageCount": 17,"detailsFetched": true,"details": {"Property Type": "Retail, Office","Sub Type": "Storefront, Medical Office","Investment Type": "Value Add","Class": "A","Tenancy": "Vacant","Square Footage": "17,000","Year Built": "2026","Buildings": "1","Lot Size (SqFt)": "35,580","APN": "1197230010001","Ground Lease": "No","Sale Condition": "For sale by owner"},"brokers": [{"name": "Chase Cooper","brokerage": "Partners"}],"sourceQuery": "Houston"}
The record above was produced with this input:
{"searchQueries": ["Houston"],"searchType": "Sales","propertyTypes": ["Retail"],"scrapeDetails": true,"maxConcurrency": 5,"maxItems": 10,"proxyConfiguration": {"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"]}}
Query and input reference
| Input | Type | Required | Default | Accepted values | Description |
|---|---|---|---|---|---|
searchQueries | array (string) | No | — | Free text (city, keyword, property name) | Search terms combined with the filters below |
startUrls | array (requestListSources) | No | — | Crexi search URLs or listing URLs | Search URLs are paginated; listing URLs collect one property |
searchType | string | No | Sales | Sales, Lease | Marketplace to search. Ignored for direct listing URLs |
propertyTypes | array (string) | No | [] | Retail, Multifamily, Office, Industrial, Hospitality, Mixed Use, Land, Self Storage, Mobile Home Park, Senior Living, Special Purpose, Note/Loan, Business for Sale | Type filter; empty includes all types |
statuses | array (string) | No | [] | On-Market, Auction, Highest & Best, Call For Offers | Sales statuses; empty uses all of these |
locations | array (string) | No | — | City names (for example Houston) | City include filter |
minPrice | integer | No | — | USD, 0 or greater | Minimum asking price; Sales searches only |
maxPrice | integer | No | — | USD, 0 or greater | Maximum asking price; Sales searches only |
scrapeDetails | boolean | No | false | true / false | Fetch listing-detail fields (charged as listing details) |
maxConcurrency | integer | No | 5 | 1–20 | Parallel detail enrichments when scrapeDetails is enabled |
maxItems | integer | No | 0 | 0 or any positive integer | Maximum listings; 0 = unlimited |
proxyConfiguration | object | No | Apify proxy, RESIDENTIAL group | Apify proxy groups or custom proxies | Residential proxies are recommended |
Provide searchQueries, startUrls, or at least one search filter.
Minimal request:
{ "searchQueries": ["Houston"], "searchType": "Sales" }
Advanced request:
{"searchQueries": ["Houston"],"searchType": "Sales","propertyTypes": ["Retail"],"statuses": ["On-Market"],"locations": ["Houston"],"minPrice": 1000000,"maxPrice": 10000000,"scrapeDetails": true,"maxConcurrency": 5,"maxItems": 20,"proxyConfiguration": {"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"]}}
Retrieve the data through the API
The Actor runs on the Apify platform. This Actor does not imply an official Crexi API.
- Start the Actor with a JSON input (console or API).
- Wait for the run to finish, or use a synchronous endpoint if you want the response inline.
- Retrieve items from the run's default dataset.
- Paginate or export the dataset.
Python example:
from apify_client import ApifyClientclient = ApifyClient("YOUR-APIFY-TOKEN")run_input = {"searchQueries": ["Houston"],"searchType": "Sales","propertyTypes": ["Retail"],"scrapeDetails": True,"maxItems": 10,}run = client.actor("datascrapers/crexi-scraper").call(run_input=run_input)for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["id"], item["propertyName"], item["city"], item["askingPrice"])
Apify generates Python, JavaScript, and cURL examples on the Actor's API tab. Do not put a real API token in shared code or URLs.
Data quality and record handling
- Conditional fields: detail fields appear only when
scrapeDetailsis enabled and the listing publishes them. Listing-only runs setdetailsFetchedtofalse. - Omitted values: asking price, lot size, class, neighborhood, NOI, and cap rate are omitted or null when Crexi does not show them. Unpriced listings still produce a dataset item.
- Source changes: unreadable fields are omitted or returned as null rather than fabricated.
- Deduplication: within a run, listings are deduplicated by
id. Across runs the Actor appends fresh records. Useid(orurl) to join repeated runs. - Failed listings: a failed listing is skipped and the run continues. The Actor stops when a spending limit is reached.
- Normalization:
detailsFetchedis a run flag.sourceQueryis the search term that produced the record. Other values are stored under the names in the data dictionary.
Export and pipeline examples
| Destination | Recommended method | Typical use |
|---|---|---|
| PostgreSQL / Supabase | Dataset API poll or webhook consumer | Store listings alongside deal-pipeline records |
| Google Sheets | Apify Google Sheets integration | Share market shortlists with acquisition teams |
| CRM | Webhook on run completion | Push new listings and broker names into outreach workflows |
| S3 / cloud storage | Scheduled export via Apify scheduler + integration | Archival of market snapshots |
Pricing and cost examples
The Actor uses pay-per-event pricing. Event rates are tiered by Apify plan. List rates:
| Event | Trigger | Rate |
|---|---|---|
| Actor start | Once per run | $0.00005 |
| dataset-item | Each listing pushed to the dataset | $0.001 per listing ($1.00 per 1,000) |
| listing-details | Each successful detail fetch when scrapeDetails is enabled | $0.002 per listing ($2.00 per 1,000) |
| Records | Configuration | Estimated base cost |
|---|---|---|
| 1,000 | Listing only | $1.00 |
| 10,000 | Listing only | $10.00 |
| 1,000 | Listing + details | $3.00 |
| 10,000 | Listing + details | $30.00 |
A listing-only run incurs Actor start plus one dataset-item event per listing. Enabling scrapeDetails adds one listing-details event per successful detail fetch. Paid Apify plans can reduce those event rates. Compute units are billed by your Apify plan. Estimates depend on the verified pricing model and selected options.
Limitations and responsible data use
- The Actor collects publicly accessible Crexi listing data only.
- Field availability depends on what Crexi renders at run time; some values can be null or missing.
- The Actor does not provide historical snapshots unless you store them yourself.
minPriceandmaxPriceapply to Sales searches only.searchTypeand status filters do not apply to direct listing URLs.- Residential proxies are recommended; coverage may degrade without them.
- You are responsible for compliance with Crexi's terms of service, applicable privacy law, and any contractual obligations before using the data.
Dataset questions
What does one dataset item represent?
One Crexi commercial listing. Brokers, the details object, and gallery URLs are nested on that listing.
Which field should I use as a unique identifier?
id is the recommended deduplication key. url is a reasonable secondary key.
Are fields nullable or conditional?
Yes. Detail fields exist when scrapeDetails is enabled and the listing publishes them. Listing-level fields Crexi does not render (for example askingPrice on an unpriced listing) are omitted or null.
Can I retrieve the records as CSV or JSON?
Yes. Export JSON, CSV, Excel, XML, or HTML from the Apify Console, or query the Dataset API.
How do I paginate large datasets?
Cap a run with maxItems. For large outputs, iterate with the Dataset API (iterate_items or offset/limit). Search startUrls are paginated during the run until maxItems or the end of results.
Does the Actor return historical data?
No. Each run captures listings at run time. Schedule repeated runs and join on id to track changes.
What counts as a billable result?
A one-time Actor start ($0.00005), a dataset-item charge per listing ($1.00 per 1,000), and a listing-details charge per successful detail fetch ($2.00 per 1,000) when scrapeDetails is enabled.
Related datasets from Data Scrapers
- Realtor.com Scraper — US residential listings that can be joined with Crexi records by city, ZIP, or coordinates.
- Redfin Scraper — US property listings and market signals for the same metro areas as Crexi inventory.
- Apartments.com Scraper — US rental listings useful alongside Crexi multifamily and mixed-use assets.
- Idealista Scraper — Spain, Italy, and Portugal property listings for cross-border real estate datasets.
- Funda Netherlands Real Estate Scraper — Netherlands property listings for comparative international research.
Data Scrapers support
Need an additional field, record type, or export workflow? Contact Data Scrapers at stardustspotlight@gmail.com. Include a sample source URL, required fields, expected record volume, and preferred delivery format.