# Century 21 Listings & Property Detail Finder (`dataspryva/century-21-listings-and-property-detail-finder`) Actor

Find Century 21 homes for sale or rent by city, county, neighborhood, or ZIP with price and size filters, or look up a property by address with photos, agent, schools, taxes, and HOA details.

- **URL**: https://apify.com/dataspryva/century-21-listings-and-property-detail-finder.md
- **Developed by:** [Dataspryva](https://apify.com/dataspryva) (community)
- **Categories:** Real estate, Lead generation, Automation
- **Features:** Limited permissions
- **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

## Century 21 Listings & Property Detail Finder

Find homes on **Century21.com** by city, county, neighborhood, ZIP, state, or a pasted URL. The actor reads Century 21's own public listing API from a plain HTTP request — no login, cookie, proxy, or API key from you — and returns clean records for **for-sale, for-rent, pending, coming-soon, sold, expired, inactive, withdrawn, rented, and canceled** listings.

It covers the full listing lifecycle rather than only active inventory: price, beds/baths, living area, lot size, year built, photos, open houses, virtual tours, MLS number, listing office, agent contact details (when the MLS publishes them), taxes, HOA dues, schools, and optional room-by-room property details.

### What this actor does

- **Four modes:** `search` by place, `byUrl` from pasted Century 21 search/listing URLs, `byAddress` with exact-address matching, `byListingId` from an ID or listing URL
- **Every public status:** active, pending, coming soon, sold, expired, inactive, withdrawn, rented, canceled
- **For sale or for rent** with the site's own rental index
- **Filters:** property type, status, price, min/max bedrooms, min bathrooms, days on market, sqft, lot size, year built, open houses, new construction, virtual tours, luxury, and sort order
- **Pagination:** up to 300 listings per request, paged until your `maxItems` or the source runs out; results are deduplicated across pages
- **Full detail enrichment:** description, taxes, HOA, schools, room descriptions, appliances, utilities, every photo, open-house windows, and agent email/phone/profile when available
- **Omit-empty output:** a field appears only when Century 21 actually returned a real value

### Output per listing

**Identity and status**

- `listingId`, `mlsNumber`, `listingUrl`, `mlsShortName`, `listingType` (For Sale / For Rent), `listingStatus`, `statusLabels[]`, `isLuxuryListing`, `isInBrand`, `daysOnMarket`, `lastUpdated`

**Price and size**

- `price`, `pricePerSquareFoot` *(details)*, `bedrooms`, `bathrooms`, `fullBathrooms`, `halfBathrooms`, `partialBathrooms`, `roomsTotal` *(details)*, `livingAreaSqFt`, `buildingAreaSqFt` *(details)*, `livingAreaUnits`, `lotSize`, `lotSizeUnits`, `yearBuilt` *(details)*

**Location**

- `address`, `city`, `state`, `stateCode`, `postalCode`, `neighborhood`, `subdivision`, `latitude`, `longitude`, `placeName`, `placeType`, `elementarySchool`, `middleSchool`, `highSchool`

**Media and events**

- `photoUrl`, `photoUrls[]`, `photosCount`, `virtualTourUrl`, `openHouses[]` (`startTime`, `endTime`)

**People and office**

- `listingOfficeName`, `listingOfficeAttribution`, `agentName`, `agentEmail`, `agentPhone`, `agentProfileUrl`, `agentId`, `agentLicense`, `agentRating`, `agentOfficeName`, `officePhone`

**Property facts** *(details where marked)*

- `description`, `taxAnnualAmount`, `taxYear`, `hoaDuesMonthly`, `numberOfUnitsInCommunity`, `heating`, `cooling`, `hasCentralAir`, `roof`, `flooring`, `foundationDetails`, `constructionMaterials`, `exteriorFeatures`, `levels`, `architectureStyle`, `basement`, `hasBasement`, `diningDescription`, `bathroomDescription`, `kitchenDescription`, `bedroomDescription`, `parkingTotal`, `garageSpaces`, `carportSpaces`, `otherParkingSpaces`, `hasGarage`, `appliances`, `amenities`, `lotFeatures`, `poolFeatures`, `laundryFeatures`, `isSmartHome`, `sewer`, `water`, `sourceUrl`

Every record also carries `recordType: "listing"` and `scrapedAt`.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` / `byUrl` / `byAddress` / `byListingId` |
| `startUrls` | array | `[]` | Century 21 search or listing URLs (mode=byUrl); query filters in the URL are honoured |
| `location` | string | – | City, county, neighborhood, ZIP, or state (mode=search); defaults to `Austin, TX` when omitted |
| `addresses` | array | `[]` | Exact street addresses (mode=byAddress); nearby non-matches are rejected |
| `listingIds` | array | `[]` | Listing IDs or listing URLs (mode=byListingId) |
| `listingType` | string | – | `forSale` / `forRent`; falls back to `forSale` in code |
| `propertyTypes` | array | `[]` | Single family, Multi-family, Co-op, Mobile/Manufactured, Lots/Land, Condominium, Townhouse, Farm; empty = all |
| `statuses` | array | `[]` | Active, Pending, Coming soon, Expired, Inactive, Withdrawn, Sold, Rented, Canceled; empty = Active + Pending + Coming soon |
| `hasOpenHouses` | bool | `false` | Only listings with an upcoming open house |
| `isNewConstruction` | bool | `false` | Only new-construction listings |
| `isVirtualTourAvailable` | bool | `false` | Only listings with a virtual tour |
| `luxuryOnly` | bool | `false` | Only Century 21 Fine Homes & Estates luxury listings |
| `minPrice` / `maxPrice` | integer | – | Price range in USD |
| `daysOnMarket` | string | – | Listed within 1, 7, 14, 30, 60, or 90 days |
| `minBedrooms` / `maxBedrooms` | string | – | Studio–5+ bedrooms |
| `minBathrooms` | string | – | 1+–5+ bathrooms |
| `minSqft` / `maxSqft` | string | – | Living-area range |
| `minAcreage` / `maxAcreage` | string | – | Lot-size range |
| `minYearBuilt` / `maxYearBuilt` | string | – | Year-built range |
| `sortBy` | string | – | `newest` / `priceHighToLow` / `priceLowToHigh`; falls back to `newest` in code |
| `includeFullDetails` | bool | `false` | Fetch full detail for every search result (one extra request per listing; search results already include the core fields) |
| `maxItems` | integer | `30` | Hard cap (1–5000) |

> Fields without a schema default show an example in the Console start form only. The actor falls back to the documented behaviour in code, so programmatic runs do not need to send every field.

#### Example: sold homes in Austin

```json
{
  "mode": "search",
  "location": "Austin, TX",
  "statuses": ["SOLD"],
  "maxItems": 100
}
```

#### Example: open houses this weekend, under $600k

```json
{
  "mode": "search",
  "location": "78704",
  "hasOpenHouses": true,
  "maxPrice": 600000,
  "maxItems": 50
}
```

#### Example: rentals with full details

```json
{
  "mode": "search",
  "location": "Miami, FL",
  "listingType": "forRent",
  "includeFullDetails": true,
  "maxItems": 20
}
```

#### Example: paste a search URL and a listing URL

```json
{
  "mode": "byUrl",
  "startUrls": [
    {"url": "https://www.century21.com/homes/list/city/tx/austin?minPrice=500000&maxPrice=900000"},
    {"url": "https://www.century21.com/homes/detail/tx/austin/803-herndon-ln/lid-P00800000HKJanssLAMoatfjovxY7QBWpsuLltxP"}
  ],
  "maxItems": 50
}
```

#### Example: exact address lookup

```json
{
  "mode": "byAddress",
  "addresses": ["803 Herndon Ln, Austin, TX 78704"]
}
```

#### Example: listing ID or listing URL

```json
{
  "mode": "byListingId",
  "listingIds": [
    "P00800000HKJanssLAMoatfjovxY7QBWpsuLltxP",
    "https://www.century21.com/homes/detail/tx/austin/803-herndon-ln/lid-P00800000HKJanssLAMoatfjovxY7QBWpsuLltxP"
  ]
}
```

### Use cases

- **Sold comparable research** — pull sold listings by ZIP or neighborhood and compare last list prices, size, and year built
- **Open-house routing** — find every upcoming open house in a target area and hand the schedule to buyers or agents
- **Agent lead lists** — export listing agent names, phones, emails, and brokerage offices with the property context attached
- **Rental market monitoring** — compare rents, deposits, and unit sizes across neighborhoods
- **Inventory and price tracking** — re-run the same search daily and diff price, status, and new listings
- **Property underwriting** — filter by lot size, year built, and square footage, then enrich the shortlist with taxes, HOA, and room details

### FAQ

**Does this need a proxy, login, or API key?** No. Century21.com's own listing API is public and works from a plain HTTP request. The actor uses no proxy and never asks for cookies or credentials.

**Can it scrape sold or off-market homes?** Yes. Century 21's public index exposes sold, expired, inactive, withdrawn, rented, and canceled statuses alongside active inventory. Select the statuses you want. A property that is not in the public index at all cannot be returned.

**How are open houses returned?** When Century 21 publishes open-house windows, each record includes an `openHouses[]` array with ISO `startTime` and `endTime`. The `hasOpenHouses` filter limits results to listings with an upcoming open house.

**What happens if I paste an address Century 21 does not list?** The actor rejects it instead of returning a nearby look-alike. Century 21's address suggestions include nearby properties even when the exact house number is missing; this actor requires the house number and street name to match, so a no-match run is empty rather than wrong data.

**Can I paste a Century 21 URL?** Yes. Search URLs (`/homes/list/...`) honour their city/county/ZIP/state/neighborhood path and any filters in the query string. Listing URLs (`.../lid-...`) fetch the full detail record. Both can be mixed in one run.

**How do I find a listing ID?** Every record from any mode includes `listingId`. You can also paste the listing's full URL.

**Why does a search result have fewer fields than a detail lookup?** Century 21's search endpoint returns a lighter record. Set `includeFullDetails: true` to fetch the full detail (description, taxes, schools, room details, all photos) for every search result; this adds one request per listing. `byAddress`, `byListingId`, and listing URLs always return full details.

**Why is an agent phone or email missing?** Contact details are published only when the listing's MLS supplies them. Most listings include an agent name and office; email and phone are less common and are omitted rather than fabricated.

**Are sold prices the final sale price?** Century 21's public sold records show the MLS list/close price it publishes for the listing. It is not an independent deed or county-recorder sale price.

**What area does this cover?** Century21.com's US market. Coverage depends on the MLS/IDX feed for each area; Century 21's country-specific sites (Canada, Portugal, Spain, France, etc.) use different systems and are not part of this actor.

**How fresh is the data?** Records are pulled live from Century 21's current public feed on every run. There is no cache.

### Limitations

- US Century21.com only; other Century 21 country domains are not supported.
- A listing must be present in Century 21's public index. Private/off-market listings are not reachable.
- Status availability varies by MLS; some feeds omit expired, inactive, or sold records entirely.
- Detail fields such as taxes, HOA, schools, room descriptions, agent email, and phone are conditional on what the listing MLS publishes. They are omitted when absent.
- `byAddress` is intentionally strict: it requires an exact house-number and street match, so spelling variants that the suggestion service cannot normalise will return zero records.

# Actor input Schema

## `mode` (type: `string`):

What to fetch. `search` resolves a place and pages its listings; `byUrl` reads pasted Century 21 search or listing URLs; `byAddress` requires an exact street-address match; `byListingId` accepts IDs or listing URLs.

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

Paste Century 21 search URLs (e.g. https://www.century21.com/homes/list/city/tx/austin) or listing URLs. Search URLs honour their type/state/area path and query filters; listing URLs fetch full details.

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

City, county, neighborhood or ZIP code, e.g. `Austin, TX`, `Miami-Dade County, FL`, `78617`.

## `addresses` (type: `array`):

Full street addresses to look up, e.g. `13521 Sea Biscuit Dr, Del Valle, TX`.

## `listingIds` (type: `array`):

Century 21 internal listing IDs (from a previous run's `listingId` field), e.g. `P00800000HF6cD2iLtM7DTj91VD8KUzhnfCsy0Wx`.

## `listingType` (type: `string`):

Search for-sale or for-rent listings. Rentals use Century 21's rental index.

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

Restrict to these property types. Leave empty for all types.

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

Restrict to these listing statuses. Leave empty for Active + Pending + Coming soon. Sold, Expired and Inactive are also available from Century 21's public index. Applied to rentals too when set.

## `hasOpenHouses` (type: `boolean`):

Only listings with an upcoming open house.

## `isNewConstruction` (type: `boolean`):

Only new-construction listings.

## `isVirtualTourAvailable` (type: `boolean`):

Only listings with a virtual tour.

## `luxuryOnly` (type: `boolean`):

Only Century 21 Fine Homes & Estates luxury listings.

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

Only listings priced at or above this amount.

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

Only listings priced at or below this amount.

## `daysOnMarket` (type: `string`):

Only listings added to the market within this many days.

## `minBedrooms` (type: `string`):

Only listings with at least this many bedrooms (0 = studio).

## `maxBedrooms` (type: `string`):

Only listings with at most this many bedrooms.

## `minBathrooms` (type: `string`):

Only listings with at least this many bathrooms.

## `minSqft` (type: `string`):

Only listings at or above this living area.

## `maxSqft` (type: `string`):

Only listings at or below this living area.

## `minAcreage` (type: `string`):

Only listings with a lot size at or above this many acres.

## `maxAcreage` (type: `string`):

Only listings with a lot size at or below this many acres.

## `minYearBuilt` (type: `string`):

Only listings built in or after this year.

## `maxYearBuilt` (type: `string`):

Only listings built in or before this year.

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

Order in which listings are returned/paginated.

## `includeFullDetails` (type: `boolean`):

Fetch the full property detail (description, taxes, HOA, schools, appliances, all photos) for every search result. Slower — makes one extra request per listing.

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

Hard cap on emitted records.

## Actor input object example

```json
{
  "mode": "search",
  "startUrls": [],
  "location": "Austin, TX",
  "addresses": [],
  "listingIds": [],
  "listingType": "forSale",
  "propertyTypes": [],
  "statuses": [],
  "hasOpenHouses": false,
  "isNewConstruction": false,
  "isVirtualTourAvailable": false,
  "luxuryOnly": false,
  "sortBy": "newest",
  "includeFullDetails": false,
  "maxItems": 3
}
```

# Actor output Schema

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

Dataset containing Century 21 listings and property details.

# 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 = {
    "mode": "search",
    "startUrls": [],
    "location": "Austin, TX",
    "addresses": [],
    "listingIds": [],
    "listingType": "forSale",
    "propertyTypes": [],
    "statuses": [],
    "hasOpenHouses": false,
    "isNewConstruction": false,
    "isVirtualTourAvailable": false,
    "luxuryOnly": false,
    "sortBy": "newest",
    "includeFullDetails": false,
    "maxItems": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("dataspryva/century-21-listings-and-property-detail-finder").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 = {
    "mode": "search",
    "startUrls": [],
    "location": "Austin, TX",
    "addresses": [],
    "listingIds": [],
    "listingType": "forSale",
    "propertyTypes": [],
    "statuses": [],
    "hasOpenHouses": False,
    "isNewConstruction": False,
    "isVirtualTourAvailable": False,
    "luxuryOnly": False,
    "sortBy": "newest",
    "includeFullDetails": False,
    "maxItems": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("dataspryva/century-21-listings-and-property-detail-finder").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 '{
  "mode": "search",
  "startUrls": [],
  "location": "Austin, TX",
  "addresses": [],
  "listingIds": [],
  "listingType": "forSale",
  "propertyTypes": [],
  "statuses": [],
  "hasOpenHouses": false,
  "isNewConstruction": false,
  "isVirtualTourAvailable": false,
  "luxuryOnly": false,
  "sortBy": "newest",
  "includeFullDetails": false,
  "maxItems": 3
}' |
apify call dataspryva/century-21-listings-and-property-detail-finder --silent --output-dataset

```

## MCP server setup

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

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/mFIgbcgtT2iThpFWD/builds/9uN11LrG2PVZf7Dux/openapi.json
