# Crexi Scraper with Agents & Financials (`fatihtahta/crexi-scraper`) Actor

Extract Crexi listings at scale with rich commercial property detail, broker contacts, deep listing metadata and market insights. Built for enterprise-grade commercial real estate intelligence, deal sourcing, and automated analytics pipelines.

- **URL**: https://apify.com/fatihtahta/crexi-scraper.md
- **Developed by:** [Fatih Tahta](https://apify.com/fatihtahta) (community)
- **Categories:** Real estate, Agents, Automation
- **Stats:** 55 total users, 19 monthly users, 100.0% runs succeeded, 2 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 property 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

**Slug:** `fatihtahta/crexi-scraper`

### Overview

Crexi Scraper collects structured commercial real estate listing records from Crexi, including property details, pricing, location, listing status, asset categories, broker information, and optional enriched listing attributes. [Crexi](https://www.crexi.com) is a commercial real estate marketplace where public sale and lease listings can provide useful signals for market research, sourcing, valuation review, and broker coverage analysis. The actor converts public listing data into repeatable JSON records that are easier to query, compare, export, and load into operational systems. It is designed for dependable recurring data acquisition workflows where consistent inputs, predictable output fields, and automation-ready datasets matter. Use it to run focused one-time searches or scheduled monitoring jobs without manually copying marketplace results.

### Why Use This Actor

- **Market research and analytics teams:** build structured extraction workflows for commercial real estate supply, asking prices, cap rates, asset classes, locations, and listing freshness.
- **Product and content teams:** populate private directories, listing experiences, market pages, or editorial datasets with normalized public property information.
- **Developers and data engineering teams:** feed downstream systems with predictable JSON records that support ETL jobs, warehouse loads, enrichment pipelines, and operational reporting.
- **Lead generation and enrichment teams:** collect public listing, broker, brokerage, and property context to qualify prospects and improve CRM records.
- **Monitoring and competitive tracking teams:** schedule repeatable collection to observe changes in availability, pricing, categories, contacts, and geographic coverage over time.

### Common Use Cases

- **Market intelligence:** monitor commercial property supply, asking price, cap rate, building size, land area, listing status, and geography.
- **Lead generation:** build targeted prospect lists from public listings, brokers, brokerages, asset classes, and locations.
- **Competitive monitoring:** track changes in active, pending, and under-contract listings across specific markets or property segments.
- **Catalog and directory building:** populate owned databases with structured commercial property records and normalized location fields.
- **Data enrichment:** add current public Crexi attributes to existing CRM, BI, underwriting, or analytics datasets.
- **Recurring reporting:** schedule periodic runs for dashboards, alerts, market snapshots, and trend analysis.
- **Deal sourcing:** screen public sale and lease opportunities by price, property type, tenancy, lease type, size, and publication date.

### Quick Start

1. Choose a `location` such as a city, state, ZIP code, neighborhood, county, or market, or leave it blank for broader discovery.
2. Select `deal_type` as `buy` or `lease`, then add optional filters such as `property_type`, `publication_date`, price, cap rate, building size, or land area.
3. Set a small `limit` for the first validation run so you can quickly inspect the output shape.
4. Run the actor in Apify Console.
5. Review the first dataset records and confirm that the fields match your workflow.
6. Increase `limit`, refine filters, enable richer records, or schedule recurring runs after the initial output is validated.

### Input Parameters

The actor accepts an optional location, keyword, listing mode, listing filters, enrichment options, coverage option, and maximum result limit.

| Parameter | Type | Description | Default |
| --- | --- | --- | --- |
| `location` | string | Optional city, state, ZIP code, neighborhood, county, or market, such as `Dallas, TX`, `Miami, FL`, or `10001`. Leave blank to search all listings. | - |
| `keyword` | string | Optional word or phrase used to narrow the search by theme, asset feature, tenant type, or other listing text. | - |
| `deal_type` | string | Listing mode. Allowed values: `buy`, `lease`. | `buy` |
| `property_type` | array of strings | One or more Crexi property categories or subcategories. Allowed values: `Retail`, `Multifamily`, `Office`, `Industrial`, `Hospitality`, `Mixed Use`, `Land`, `Self Storage`, `Mobile Home Park`, `Senior Living`, `Special Purpose`, `Note/Loan`, `Business for Sale`, `Bank`, `Convenience Store`, `Day Care/Nursery`, `QSR/Fast Food`, `Gas Station`, `Grocery Store`, `Pharmacy/Drug`, `Restaurant`, `Bar`, `Storefront`, `Shopping Center`, `Auto Shop`, `Student Housing`, `Single Family Rental Portfolio`, `RV Park`, `Apartment Building`, `Traditional Office`, `Executive Office`, `Medical Office`, `Creative Office`, `Distribution`, `Flex`, `Warehouse`, `R&D`, `Manufacturing`, `Refrigerated/Cold Storage`, `Hotel`, `Motel`, `Casino`, `Agricultural (Land)`, `Residential (Land)`, `Commercial (Land)`, `Industrial (Land)`, `Islands (Land)`, `Farm (Land)`, `Ranch (Land)`, `Timber (Land)`, `Hunting/Recreational (Land)`, `Telecom/Data Center`, `Sports/Entertainment`, `Marina`, `Golf Course`, `School`, `Religious/Church`, `Garage/Parking`, `Car Wash`, `Airport`, `Business Only`, `Business and Building`. Leave empty to include all supported property types. | - |
| `tenancy` | array of strings | One or more tenancy statuses. Allowed values: `Vacant`, `Single`, `Multi`. | - |
| `lease_type` | array of strings | One or more lease structures. Allowed values: `Net`, `NNN`, `Absolute Net`, `Gross`, `Modified`, `Ground`. | - |
| `opportunity_zone` | boolean | When enabled, keeps only listings marked as located in an Opportunity Zone. | `false` |
| `publication_date` | string | Listing recency filter. Allowed values: `24_hours`, `3_days`, `7_days`, `14_days`, `30_days`, `90_days`, `6_months`, `365_days`. | - |
| `building_quality_class` | array of strings | One or more building quality classes. Allowed values: `A`, `B`, `C`, `D`. | - |
| `listing_status` | array of strings | Listing statuses to include. Allowed values: `active_listing`, `contract_pending`, `under_contract`. | `["active_listing"]` |
| `min_cap_rate` | number | Minimum capitalization rate percentage to include. Allowed range: `0.1` to `15`. | - |
| `max_cap_rate` | number | Maximum capitalization rate percentage to include. Allowed range: `0.1` to `15`. | - |
| `min_remaining_term` | integer | Minimum remaining lease term, in years. Allowed range: `1` to `100`. | - |
| `max_remaining_term` | integer | Maximum remaining lease term, in years. Allowed range: `1` to `100`. | - |
| `min_price` | integer | Minimum asking price for sale listings, in listing currency where available. | - |
| `max_price` | integer | Maximum asking price for sale listings, in listing currency where available. | - |
| `min_price_per_sf` | integer | Minimum price per square foot. For sale searches, this represents sale price per square foot; for lease searches, annual base rent per square foot. | - |
| `max_price_per_sf` | integer | Maximum price per square foot. For sale searches, this represents sale price per square foot; for lease searches, annual base rent per square foot. | - |
| `min_building_area` | integer | Minimum building size in square feet. | - |
| `max_building_area` | integer | Maximum building size in square feet. | - |
| `min_land_area` | number | Minimum land area in acres. | - |
| `max_land_area` | number | Maximum land area in acres. | - |
| `enrich_data` | boolean | Collects richer listing details such as descriptions, highlights, property facts, suites, tenants, and location details when available. | `true` |
| `get_contacts` | boolean | Includes available listing broker and brokerage contact details when available. | `true` |
| `maximize_coverage` | boolean | Collects more matching sale listings for broad sale searches. Use `false` for faster exploratory runs or lease searches where standard collection is enough. | `true` |
| `limit` | integer | Maximum number of listings to save. Minimum: `1`. The input form may prefill `100`; leave empty to collect eligible results until no more matching records are available. | - |

### Choosing Inputs

Use `location` to define the target market and `keyword` when the market alone is too broad. Choose `deal_type` first because sale and lease workflows use different screening criteria in practice. Add `property_type`, `tenancy`, `lease_type`, `listing_status`, `publication_date`, and building quality filters when you need a more targeted dataset; leave optional filters empty when discovery is more important than precision. Price, cap rate, remaining term, building area, and land area fields control numeric scope and are useful for underwriting, sourcing, and reporting. Start with a small `limit`, confirm the dataset shape, then increase the limit or schedule the actor once the output matches your use case.

### Example Inputs

#### Example: Miami retail sale search

```json
{
  "location": "Miami, FL",
  "deal_type": "buy",
  "property_type": ["Retail", "Convenience Store"],
  "min_cap_rate": 4,
  "max_price": 15000000,
  "enrich_data": true,
  "get_contacts": true,
  "limit": 25
}
```

#### Example: Recently published lease opportunities

```json
{
  "location": "Dallas, TX",
  "deal_type": "lease",
  "property_type": ["Office", "Medical Office"],
  "publication_date": "30_days",
  "min_building_area": 5000,
  "enrich_data": true,
  "limit": 50
}
```

#### Example: Broad discovery with conservative output

```json
{
  "keyword": "industrial outdoor storage",
  "deal_type": "buy",
  "property_type": ["Industrial", "Land"],
  "listing_status": ["active_listing"],
  "maximize_coverage": true,
  "enrich_data": false,
  "get_contacts": false,
  "limit": 100
}
```

### Output

#### Output destination

The actor writes results to the default Apify dataset as JSON records. Each normal row uses one normalized commercial real estate listing shape with `record_type` set to `property_listing`.

#### Record envelope and stable identifiers

Each dataset item represents one Crexi listing. Use `record_id` as the primary deduplication and upsert key. `record_id` is the Crexi listing ID stored as a string. `source_context.fingerprint` is also included as a compact actor-generated signature for duplicate detection and change checks.

The public listing URL is available in `entity.url`, `source_context.source_url`, and `source_context.listing_url`. Search provenance such as `seed_id`, `seed_type`, `seed_value`, and `page_index` is grouped under `source_context`.

#### Example

##### Example: property listing record

```json
{
  "record_type": "property_listing",
  "record_id": "904218",
  "source_context": {
    "source_name": "Crexi",
    "source_domain": "www.crexi.com",
    "source_url": "https://www.crexi.com/properties/904218/texas-net-leased-retail-property",
    "listing_url": "https://www.crexi.com/properties/904218/texas-net-leased-retail-property",
    "fingerprint": "9f2c7a4d81b6e305c4a1",
    "external_ids": {
      "crexi_listing_id": "904218"
    },
    "seed_id": "a4c9e2b71f0d63842b5e",
    "seed_type": "search",
    "seed_value": "Austin, TX",
    "page_index": 1
  },
  "entity": {
    "title": "Net Leased Retail Property",
    "description": "Retail | 5.25% CAP | 6,120 SF",
    "url": "https://www.crexi.com/properties/904218/texas-net-leased-retail-property",
    "status": "Active",
    "category": "commercial_property",
    "external_ids": {
      "crexi_listing_id": "904218"
    }
  },
  "listing": {
    "listing_id": "904218",
    "deal_type": "buy",
    "listing_status": "Active",
    "activated_at": "2025-03-14T10:24:18.000Z",
    "updated_at": "2026-04-22T15:18:43.000Z",
    "investment_highlights": "Newer construction with long-term single-tenant occupancy and scheduled rent increases."
  },
  "pricing": {
    "asking_price": 7850000.0,
    "price_per_sqft": 1282.6797385620914
  },
  "location": {
    "address": "1000 Market Center Drive",
    "full_address": "1000 Market Center Drive, Austin, Travis County, TX 78701",
    "city": "Austin",
    "county": "Travis County",
    "state": "TX",
    "postal_code": "78701",
    "latitude": 30.267153,
    "longitude": -97.743057,
    "is_in_opportunity_zone": false
  },
  "property": {
    "property_types": [
      "Retail"
    ],
    "property_subtypes": [
      "Convenience Store"
    ],
    "building_area_sqft": 6120,
    "lot_size_acres": 1.35,
    "tenancy": "Single",
    "details": {
      "Asking Price": "$7,850,000",
      "Property Type": "Retail",
      "Sub Type": "Convenience Store",
      "Cap Rate": "5.25%"
    }
  },
  "media": {
    "thumbnail_url": "https://images.crexi.com/assets/904218/sample-retail-property_716x444.jpg",
    "has_offering_memorandum": true,
    "has_flyer": false,
    "has_video": false,
    "has_virtual_tour": false
  },
  "contact_details": {
    "contact_count": 1
  },
  "relationships": {
    "agency": {
      "name": "Northstar Commercial Advisors"
    },
    "agents": [
      {
        "id": "2004",
        "full_name": "Sample Broker",
        "email": "broker@example.com",
        "phone": "555-0100",
        "public_profile_id": "samplebroker",
        "brokerage": {
          "name": "Northstar Commercial Advisors"
        }
      }
    ]
  },
  "metrics": {
    "cap_rate": 5.25,
    "contact_count": 1
  },
  "attributes": {
    "source_specific": {
      "number_of_images": 6,
      "price_per_acre_land": "$5,814,815/Acre",
      "vault_access_status": "AuthRequired"
    }
  }
}
```

Lease listings use the same `property_listing` envelope. Lease rates appear under `pricing.rate_yearly`, `pricing.rate_monthly`, `pricing.rate_yearly_per_sqft`, or `pricing.rate_monthly_per_sqft` when available. Suite-level availability is preserved under `availability.suites`.

### Field Reference

#### Top-level fields

**record\_type** *(string, required)*: Stable row discriminator. Normal Crexi listing rows use `property_listing`.

**record\_id** *(string, required)*: Stable Crexi listing identifier, stored as a string for safe upserts.

**source\_context** *(object, required)*: Provenance and run context. Includes source name, source domain, public listing URLs, the actor fingerprint, Crexi external IDs, seed fields, and page index when available.

**entity** *(object, required)*: Main display identity for the listing, including title, description, public URL, status, category, and external IDs.

**listing** *(object, optional)*: Listing-level business context such as listing ID, deal type, listing status, timestamps, state flags, marketing description, and investment highlights.

**pricing** *(object, optional)*: Sale and lease pricing fields, including asking price, price per square foot, yearly/monthly lease rates, per-square-foot lease rates, and unpriced status.

**location** *(object, optional)*: Address, city, county, state, postal code, coordinates, submarket, Opportunity Zone flag, visibility flags, and source property-location identifiers when available.

**property** *(object, optional)*: Physical and commercial property facts such as property types, subtypes, building area, lot size, unit count, tenancy, tenants, building highlights, source detail facts, and summary details.

**availability** *(object, optional)*: Lease suite and availability data. `availability.suites` preserves suite IDs, names, space uses, rates, floor plans, gallery media, status, and source-provided suite configuration fields.

**media** *(object, optional)*: Listing thumbnail URL and public media/material flags such as offering memorandum, flyer, video, and virtual tour availability.

**contact\_details** *(object, optional)*: Contact summary fields, including `contact_count` when broker contact data is collected.

**relationships** *(object, optional)*: Linked real estate entities. `relationships.agency` stores brokerage context, and `relationships.agents` stores public broker/contact records with IDs, names, phone, email, profile IDs, brokerage details, licenses, badges, and capabilities when available.

**metrics** *(object, optional)*: Numeric signals such as capitalization rate, net operating income, and contact count.

**attributes** *(object, optional)*: Preservation bucket for meaningful Crexi-specific values that do not fit a stronger normalized group. Source-specific fields are grouped under `attributes.source_specific`.

#### Common nested paths

**source\_context.source\_name** *(string)*: Source label, usually `Crexi`.

**source\_context.source\_domain** *(string)*: Public source domain, usually `www.crexi.com`.

**source\_context.source\_url / source\_context.listing\_url** *(string)*: Public Crexi listing URL.

**source\_context.fingerprint** *(string)*: Actor-generated compact record fingerprint.

**source\_context.external\_ids.crexi\_listing\_id** *(string)*: Crexi listing ID.

**source\_context.seed\_id / source\_context.seed\_type / source\_context.seed\_value / source\_context.page\_index** *(string or number)*: Search context that produced the row.

**entity.title / entity.description / entity.url / entity.status** *(string)*: Main listing identity fields.

**listing.deal\_type** *(string)*: Listing mode, such as `buy` or `lease`.

**listing.listing\_status** *(string)*: Source listing status.

**listing.created\_at / listing.activated\_at / listing.updated\_at** *(string)*: Source listing timestamps when available.

**pricing.asking\_price** *(number or string)*: Asking price when available.

**pricing.price\_per\_sqft** *(number or string)*: Sale price per square foot when available.

**pricing.rate\_yearly / pricing.rate\_monthly** *(string)*: Display lease rate fields when available.

**pricing.rate\_yearly\_per\_sqft / pricing.rate\_monthly\_per\_sqft** *(string)*: Display lease rate per square foot fields when available.

**location.address / location.full\_address / location.city / location.county / location.state / location.postal\_code** *(string)*: Listing address fields.

**location.latitude / location.longitude** *(number or string)*: Listing coordinates when available.

**location.verified** *(object)*: Source-provided verified city or state values when available.

**property.property\_types / property.property\_subtypes** *(array)*: Commercial property categories and subcategories.

**property.building\_area\_sqft / property.lot\_size\_acres / property.number\_of\_units** *(number or string)*: Physical property size and unit facts.

**property.details** *(object)*: Source display facts such as formatted price, cap rate, year built, lot size, tenancy, lease terms, tenant names, and similar listing details.

**property.summary\_details** *(array)*: Structured source summary facts with labels, values, and display strings.

**availability.suites** *(array)*: Lease suite records, including source suite IDs, names, rentable square feet, rates, rate ranges, floor plan URLs, gallery items, lease type, status, and suite configuration.

**media.thumbnail\_url** *(string)*: Listing thumbnail image URL.

**relationships.agency.name** *(string)*: Brokerage name associated with the listing.

**relationships.agents** *(array)*: Public broker/contact records when contact enrichment is enabled and contacts are available.

**metrics.cap\_rate / metrics.net\_operating\_income** *(number or string)*: Commercial investment metrics when available.

**attributes.source\_specific** *(object)*: Source-specific Crexi values, flags, labels, counts, and preserved attributes that do not belong in the normalized groups.

### Data Quality, Guarantees, And Handling

- **Structured records:** results are normalized into predictable JSON objects for downstream use.
- **Best-effort extraction:** fields may vary by region, session, availability, listing type, and target-side experiments.
- **Optional fields:** null-check optional fields in downstream code, especially enriched details, contact data, media flags, and location attributes.
- **Deduplication:** use `record_id` as the primary stable key, with `entity.url` or `source_context.fingerprint` as secondary keys when needed.
- **Freshness:** results reflect the publicly available data at run time.
- **Repeated runs:** use the recommended idempotency key when syncing data into warehouses, CRMs, or search indexes.

### Tips For Best Results

- Start with a small `limit` to validate the output shape before scaling up.
- Use one geography, property type, or market segment per run when you need cleaner segmentation.
- Leave optional filters empty when the goal is broad discovery.
- Add price, cap rate, area, tenancy, and publication filters gradually to understand how each field changes coverage.
- Use `enrich_data` when listing details, highlights, tenants, and property facts matter more than speed.
- Use `get_contacts` when broker and brokerage data is part of the workflow.
- Use stable identifiers such as `record_id`, `entity.url`, and `source_context.fingerprint` when storing results over time.

### How to Run on Apify

1. Open the Actor in Apify Console.
2. Configure the available input fields for the target scope, such as location, listing mode, property type, recency, price, size, and enrichment options.
3. Set the maximum number of outputs to collect with `limit`.
4. Click **Start** and wait for the run to finish.
5. Open the dataset and inspect the first records.
6. Download results in JSON, CSV, Excel, or another supported Apify dataset format.

### Scheduling & Automation

#### Scheduling

**Automated Data Collection**

Use Apify schedules to run Crexi Scraper on a recurring cadence and keep your commercial real estate dataset current. Scheduled runs are useful for market monitoring, lead enrichment, dashboard refreshes, and recurring reporting.

- Navigate to **Schedules** in Apify Console
- Create a new schedule, such as daily, weekly, or custom cron
- Configure input parameters
- Enable notifications for run completion
- Add webhooks for automated processing

#### Integration Options

- **CRM enrichment:** sync public listing, broker, brokerage, location, and property attributes into lead or account records.
- **BI dashboards:** monitor pricing, cap rates, availability, status changes, and market coverage over time.
- **Data warehouses:** load normalized listing records into Snowflake, BigQuery, Redshift, or another analytics store for historical analysis.
- **Google Sheets or Airtable:** review smaller market slices, qualification lists, and broker outreach queues in spreadsheet-style workflows.
- **Webhooks:** trigger ingestion, validation, alerting, or notification workflows after each completed run.
- **Data enrichment pipelines:** join Crexi listing records with proprietary property, parcel, CRM, or underwriting datasets.

### Export Formats And Downstream Use

Apify datasets can be exported from the Console or consumed programmatically by downstream systems. Use the format that best matches your workflow and data volume.

- **JSON:** for APIs, applications, and data pipelines
- **CSV or Excel:** for spreadsheet workflows and manual review
- **API access:** for automated ingestion into business systems
- **BI and warehouses:** for reporting, dashboards, and historical analysis

### Performance

Estimated run times:

- **Small runs (< 1,000 outputs):** ~3-5 minutes
- **Medium runs (1,000-5,000 outputs):** ~5-15 minutes
- **Large runs (5,000+ outputs):** ~15-30 minutes

Execution time varies based on filters, result volume, and how much information is returned per record. Highly filtered runs can finish faster, while broad discovery or detail-rich records may take longer.

### Limitations

- Availability depends on what <https://www.crexi.com> publicly exposes at run time.
- Some optional fields may be missing on sparse listings, lease records, records without contacts, or listings with limited public details.
- Very broad searches may take longer or require higher `limit` values to collect the desired volume.
- Target-side changes can affect field availability, naming, or whether a specific detail is visible.
- Regional, account, or availability differences may change visible results.
- Contact details are included only when available in the public listing data and when `get_contacts` is enabled.

### Troubleshooting

- **No results returned:** check filter combinations, location spelling, property type selection, keyword specificity, and whether Crexi has matching public records.
- **Fewer results than expected:** broaden filters, raise `limit`, remove restrictive recency or numeric ranges, or verify that enough matching records exist.
- **Some fields are empty:** optional fields depend on what each listing publicly provides.
- **Run takes longer than expected:** reduce scope, lower `limit` for validation, or split broad collection into smaller market or property-type segments.
- **Output changed:** compare the current output with the field reference and include a small sample when requesting support.

### FAQ

#### What data does this actor collect?

It collects public Crexi commercial real estate listing records, including listing identifiers, URLs, titles, descriptions, pricing, property types, status, location fields, property facts, optional enrichment details, and optional broker contact information.

#### Can I filter by location, category, date, price, or other criteria?

Yes. The input supports `location`, `keyword`, `deal_type`, `property_type`, `publication_date`, listing status, tenancy, lease type, building quality, price, price per square foot, cap rate, remaining lease term, building area, land area, and Opportunity Zone filtering.

#### Why did I receive fewer results than my limit?

The actor can only save matching public records that are available for the configured scope. Restrictive filters, sparse markets, narrow recency windows, or limited public availability can produce fewer records than the requested `limit`.

#### Can I schedule recurring runs?

Yes. Use Apify schedules to run the actor daily, weekly, or on a custom cron schedule with the same input configuration.

#### How do I avoid duplicates across runs?

Use `record_id` as the primary deduplication and upsert key. You can also store `entity.url` and `source_context.fingerprint` as secondary identifiers for validation and change tracking.

#### Can I export the data to CSV, Excel, or JSON?

Yes. Apify datasets support JSON, CSV, Excel, and other export formats from the Apify Console.

#### Does this actor collect private data?

No. It is intended to collect publicly available listing and contact information from Crexi. Users are responsible for using the data lawfully and respecting privacy requirements.

#### Should I enable enriched data and contacts?

Enable `enrich_data` when property facts, highlights, tenants, and detailed listing attributes are important. Enable `get_contacts` when broker and brokerage details are needed for review, enrichment, or outreach workflows.

#### What should I include when reporting an issue?

Include the input used with sensitive values redacted, the run ID, expected versus actual behavior, and a small output sample when available.

### Compliance & Ethics

#### Responsible Data Collection

This actor collects publicly available commercial real estate listing information from **https://www.crexi.com** for legitimate business purposes, including:

- **Commercial real estate** research and market analysis
- **Property sourcing, underwriting, and lead enrichment**
- **Market monitoring, reporting, and competitive intelligence**

Users are responsible for ensuring that their use of collected data complies with applicable laws, regulations, contractual obligations, and the target site's terms. This section is informational and not legal advice.

#### Best Practices

- Use collected data in accordance with applicable laws, regulations, and the target site's terms
- Respect individual privacy and personal information
- Use data responsibly and avoid disruptive or excessive collection
- Do not use this actor for spamming, harassment, or other harmful purposes
- Follow relevant data protection requirements where applicable, such as GDPR and CCPA

### Support

For help, use the actor page or Issues. Include the input used with sensitive values redacted, the run ID, expected versus actual behavior, and a small output sample if it helps demonstrate the issue. Avoid including private credentials, confidential data, or unnecessary personal information in support requests.

# Actor input Schema

## `deal_type` (type: `string`):

Choose whether to collect commercial properties for sale or spaces available for lease. Some filters are more useful for one listing mode than the other.

## `location` (type: `string`):

Choose the market area to search. Use a city and state, ZIP code, neighborhood, county, or state; leave empty to include listings from any location.

## `property_type` (type: `array`):

Select one or more Crexi property types to include. Leave empty to keep all supported property types eligible.

## `tenancy` (type: `array`):

Select one or more tenancy statuses to include. Leave empty when vacant, single-tenant, and multi-tenant listings should all remain eligible.

## `lease_type` (type: `array`):

Select one or more lease types to include. Leave empty when any supported lease structure is acceptable.

## `opportunity_zone` (type: `boolean`):

Enable this to keep only listings marked as located in an Opportunity Zone. Leave it off to include listings regardless of Opportunity Zone status.

## `publication_date` (type: `string`):

Select how recently listings should have been published. Leave empty to include listings regardless of publication date.

## `building_quality_class` (type: `array`):

Select one or more building classes to include. Leave empty when all supported quality classes should remain eligible.

## `listing_status` (type: `array`):

Select one or more listing statuses to include. Keep the default for active listings, or add pending and under-contract statuses when they are useful for your workflow.

## `keyword` (type: `string`):

Enter an optional word or phrase to narrow the search. Leave empty when the location and selected filters are enough.

## `min_cap_rate` (type: `number`):

Enter the lowest cap rate percentage to include. Leave empty when there is no minimum cap rate requirement.

## `max_cap_rate` (type: `number`):

Enter the highest cap rate percentage to include. Leave empty when there is no maximum cap rate requirement.

## `min_remaining_term` (type: `integer`):

Enter the lowest remaining term, in years, to include. Leave empty when there is no minimum term requirement.

## `max_remaining_term` (type: `integer`):

Enter the highest remaining term, in years, to include. Leave empty when there is no maximum term requirement.

## `min_price` (type: `integer`):

Enter the lowest asking price to include for sale listings. Leave empty when there is no lower price requirement.

## `max_price` (type: `integer`):

Enter the highest asking price to include for sale listings. Leave empty when there is no upper price requirement.

## `min_price_per_sf` (type: `integer`):

Enter the lowest per-square-foot value to include. Leave empty when there is no lower per-square-foot requirement.

## `max_price_per_sf` (type: `integer`):

Enter the highest per-square-foot value to include. Leave empty when there is no upper per-square-foot requirement.

## `min_building_area` (type: `integer`):

Enter the smallest building size to include, in square feet. Leave empty when there is no minimum building-size requirement.

## `max_building_area` (type: `integer`):

Enter the largest building size to include, in square feet. Leave empty when there is no maximum building-size requirement.

## `min_land_area` (type: `number`):

Enter the smallest land area to include, in acres. Leave empty when there is no minimum land-area requirement.

## `max_land_area` (type: `number`):

Enter the largest land area to include, in acres. Leave empty when there is no maximum land-area requirement.

## `enrich_data` (type: `boolean`):

Enable this for more complete property listings. This may make the run slower because the actor may spend more time collecting details for each result. Turn it off for faster runs when the standard result fields are enough.

## `get_contacts` (type: `boolean`):

Enable this to include available broker and brokerage details for saved listings. This can make runs slower, so leave it off when listing-level data is enough.

## `maximize_coverage` (type: `boolean`):

Enable this when a large sale search needs broader collection. Turn it off for faster exploratory runs or lease searches where the standard collection flow is enough.

## `limit` (type: `integer`):

Enter the maximum number of listings to save. Leave empty to keep collecting matching listings until the run has no more eligible results to save.

## Actor input object example

```json
{
  "deal_type": "buy",
  "location": "SOHO Manhattan NY",
  "opportunity_zone": false,
  "listing_status": [
    "active_listing"
  ],
  "enrich_data": true,
  "get_contacts": true,
  "maximize_coverage": true
}
```

# Actor output Schema

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

No description

# 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 = {
    "location": "SOHO Manhattan NY"
};

// Run the Actor and wait for it to finish
const run = await client.actor("fatihtahta/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 = { "location": "SOHO Manhattan NY" }

# Run the Actor and wait for it to finish
run = client.actor("fatihtahta/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 '{
  "location": "SOHO Manhattan NY"
}' |
apify call fatihtahta/crexi-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fatihtahta/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/OrmVLngc0GRKvmwWY/builds/F1KmvS6bInxkj4HLd/openapi.json
