StreetEasy Listing Monitor avatar

StreetEasy Listing Monitor

Pricing

Pay per event

Go to Apify Store
StreetEasy Listing Monitor

StreetEasy Listing Monitor

Snapshot and monitor public StreetEasy NYC sale and rental searches with normalized prices, status, days on market, broker, and change metadata.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Stas Persiianenko

Stas Persiianenko

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

10 days ago

Last modified

Categories

Share

StreetEasy Listing Monitor turns public NYC sale and rental searches into stable, normalized listing records.

Use it as a StreetEasy scraper for one-time apartment research or schedule repeat runs to identify new, repriced, status-changed, updated, and removed listings.

Each record includes a stable listing ID, current price, source status, source-derived days on market, broker label, property facts, coordinates, and observation metadata.

The Actor supports public borough and all-NYC search URLs for rentals and sales.

It does not require a StreetEasy account.

What does StreetEasy Listing Monitor do?

The Actor accepts one or more public StreetEasy search URLs.

It queries the same structured listing service used by the public site, normalizes sale and rental results, and stores them in the default Apify dataset.

For every accepted listing it also retrieves the source creation timestamp used to calculate daysOnMarket.

With monitoring enabled, the Actor stores a private snapshot under a hash of your stateKey.

Later runs compare the current snapshot with that prior state.

The result is ready for spreadsheets, databases, dashboards, webhooks, and scheduled market-monitoring workflows.

Who is it for?

  • Real estate analysts tracking NYC asking-price and inventory movements.
  • Buyer agents building current sale comps for a borough.
  • Rental teams monitoring new StreetEasy apartments in Brooklyn or Manhattan.
  • Investors watching listings for price or status changes.
  • Data teams that need consistent records instead of page-specific HTML.
  • Developers building a private StreetEasy data pipeline through the Apify API.

This Actor is designed for inventory observation.

It does not contact brokers, submit forms, log in, or collect private account data.

Why use normalized listing snapshots?

StreetEasy pages are useful for browsing, but repeated analysis benefits from stable fields.

The Actor uses listingType + listingId as the comparison identity.

It records both source timestamps and observation timestamps.

That distinction helps answer two different questions:

  1. When did StreetEasy create or update this listing?
  2. When did my own workflow first and most recently observe it?

The sourceFingerprint hashes change-relevant fields so downstream systems can deduplicate observations.

Supported StreetEasy search URLs

Use HTTPS search pages for all NYC or one borough.

Supported rental forms include:

  • https://streeteasy.com/for-rent/nyc
  • https://streeteasy.com/for-rent/manhattan
  • https://streeteasy.com/for-rent/brooklyn
  • https://streeteasy.com/for-rent/queens
  • https://streeteasy.com/for-rent/bronx
  • https://streeteasy.com/for-rent/staten-island

Replace for-rent with for-sale for sale inventory.

Unsupported hosts, listing detail URLs, building pages, arbitrary neighborhood slugs, and non-HTTPS URLs fail closed with a clear input error.

What StreetEasy data is extracted?

FieldMeaning
listingIdStable StreetEasy listing ID
listingTyperent or sale
urlCanonical public listing URL
street, unitSource address and unit
areaNameStreetEasy neighborhood label
price, currencyCurrent asking price or monthly rent in USD
priceDeltaLatest source-reported price change when available
statusCurrent source listing status
listedAtSource listing creation timestamp
updatedAtLatest source update timestamp
daysOnMarketWhole days since listedAt
bedroomsBedroom count
bathrooms, halfBathroomsFull and half bathroom counts
livingAreaSquareFeetReported living area when available
buildingTypeSource building classification
brokerNameBrokerage or source-group label
sourceTypeStreetEasy ingestion source classification
latitude, longitudeListing coordinates
sourceSearchUrlInput URL that produced the record
sourcePageOne-based result page; zero for removed records
observedAtCurrent run observation timestamp
firstSeenAtFirst observation timestamp for this monitor
changeTypeComparison classification
previousPrice, previousStatusPrior monitor values
sourceFingerprintHash of change-relevant source fields

Source fields may be null when StreetEasy does not provide a value.

Getting started

  1. Open the Actor input page.
  2. Add a supported StreetEasy NYC sale or rental search URL.
  3. Set maxItems to the number of records you need.
  4. Keep maxPages small for an initial run.
  5. Click Start.
  6. Open the default dataset and select the StreetEasy listings view.
  7. Export JSON, CSV, Excel, XML, or RSS as needed.

A useful first input is:

{
"startUrls": [
{ "url": "https://streeteasy.com/for-rent/brooklyn" }
],
"maxItems": 20,
"maxPages": 1
}

Input parameters

startUrls

Required array of supported public StreetEasy search URLs.

You can mix sale and rental searches in one run.

maxItems

Maximum number of output records across all input searches.

Default: 50.

Allowed range: 1 to 5000.

maxPages

Maximum structured result pages fetched for each search.

Default: 10.

Allowed range: 1 to 100.

monitoring

Set to true to compare the current inventory with stored prior state.

stateKey

Required when monitoring is enabled.

Choose a stable private value for one logical monitor, such as brooklyn-rental-watch.

The Actor hashes this value before constructing the key-value store key.

emitUnchanged

Include UNCHANGED records in monitoring runs.

It defaults to false so scheduled runs can produce a compact change feed.

emitRemoved

Emit REMOVED records that existed in a prior complete snapshot but are absent now.

Removal detection is skipped when maxItems or maxPages truncates the current snapshot, preventing false removals.

Output example

A current rental record has this shape:

{
"listingId": "5118281",
"listingType": "rent",
"url": "https://streeteasy.com/building/97-grand-avenue-brooklyn/4b",
"street": "97 Grand Avenue",
"unit": "4B",
"areaName": "Clinton Hill",
"price": 4565,
"currency": "USD",
"status": "ACTIVE",
"daysOnMarket": 0,
"listedAt": "2026-07-30T01:05:02.000-04:00",
"bedrooms": 2,
"bathrooms": 2,
"brokerName": "Brighton Management",
"sourceSearchUrl": "https://streeteasy.com/for-rent/brooklyn",
"changeType": "NEW",
"previousPrice": null,
"observedAt": "2026-07-30T05:29:23.554Z"
}

The full dataset also includes update timestamps, coordinates, source classifications, comparison metadata, and the source fingerprint.

How does change monitoring work?

The first run for a new stateKey classifies observed listings as NEW.

Later runs use these values:

  • NEW: not present in prior state.
  • PRICE_CHANGED: current price differs from prior price.
  • STATUS_CHANGED: source status differs from prior status.
  • UPDATED: another fingerprinted source field changed.
  • UNCHANGED: no fingerprinted field changed.
  • REMOVED: absent from a complete current snapshot.

Use one stateKey per independent search set.

Reusing the same key for unrelated URLs merges their comparison state.

Schedule a StreetEasy price and status monitor

Create an Apify Schedule after a successful first run.

Hourly or daily frequency is usually more appropriate than rapid polling.

A change-feed input can look like this:

{
"startUrls": [
{ "url": "https://streeteasy.com/for-sale/manhattan" }
],
"maxItems": 500,
"maxPages": 10,
"monitoring": true,
"stateKey": "manhattan-sale-watch",
"emitUnchanged": false,
"emitRemoved": true
}

Connect the schedule to a webhook, Make, Zapier, Slack workflow, or database loader.

Treat REMOVED as an observed absence, not proof that a property sold.

How much does it cost to monitor StreetEasy listings?

The Actor uses pay-per-event pricing.

Each run has a one-time $0.005 start event.

Each accepted listing or change record uses the item event.

The BRONZE item price is $0.0018 before higher-plan volume-tier discounts.

At that price, 20 records cost about $0.041, 100 records about $0.185, and 1,000 records about $1.805 on BRONZE.

These examples cover Actor event charges.

Your Apify plan and platform usage accounting may also apply.

The Console shows the final charge for every run.

No separate event is charged for detail enrichment, monitoring state, or removed records.

Efficient and reliable usage

  • Start with 10–20 items before increasing limits.
  • Keep all URLs for one logical monitor in the same scheduled Task.
  • Use emitUnchanged: false when downstream systems only need changes.
  • Use a sufficiently high limit before enabling removed detection.
  • Avoid launching many overlapping runs with the same stateKey.
  • Keep schedules at a responsible interval.
  • Inspect completeSnapshot warnings in logs before interpreting removals.

The Actor uses a coherent US residential proxy session because direct and datacenter requests are challenged by the source.

It rotates only after a verified challenge or transient upstream failure.

Limitations and failure behavior

StreetEasy can change its public structured service or anti-bot controls.

A challenged session is retried with a bounded fresh identity.

The run fails after three blocked sessions rather than returning a false successful empty dataset.

Only public all-NYC and borough search URLs are supported in this version.

Neighborhood-specific path parsing and arbitrary search-filter query parameters are not yet translated into structured filters.

StreetEasy may report zero for unknown living area.

daysOnMarket is calculated from the source listing creation timestamp and may not represent cumulative marketing periods across relistings.

Broker names are source-provided labels, not independently verified identities.

Removed records omit property fields that are not retained in monitor state.

Export and integration patterns

Common workflows include:

  1. Export a one-time Brooklyn rental snapshot to CSV.
  2. Load Manhattan sale listings into a warehouse for price analysis.
  3. Send only PRICE_CHANGED records to a Slack webhook.
  4. Build a daily borough inventory dashboard.
  5. Join stable IDs across runs to calculate your own observed history.
  6. Trigger a review when status changes away from ACTIVE.

The default dataset is backward-compatible with Apify integrations.

Use the overview view for a compact table or fetch all fields through the API.

Run with the Apify API using cURL

curl -X POST \
"https://api.apify.com/v2/acts/automation-lab~streeteasy-listing-monitor/runs?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"startUrls": [{"url":"https://streeteasy.com/for-rent/nyc"}],
"maxItems": 20,
"maxPages": 1
}'

Poll the returned run or use the synchronous dataset endpoint when appropriate.

Never commit your Apify token to source control.

Run with JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/streeteasy-listing-monitor').call({
startUrls: [{ url: 'https://streeteasy.com/for-sale/manhattan' }],
maxItems: 50,
maxPages: 2,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

Run with Python

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("automation-lab/streeteasy-listing-monitor").call(run_input={
"startUrls": [{"url": "https://streeteasy.com/for-rent/brooklyn"}],
"maxItems": 20,
"maxPages": 1,
})
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)

Use StreetEasy data through MCP

Add the Apify MCP server to Claude Code:

claude mcp add --transport http apify \
"https://mcp.apify.com?tools=automation-lab/streeteasy-listing-monitor"

Claude Desktop, Cursor, and VS Code can use this HTTP MCP configuration:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=automation-lab/streeteasy-listing-monitor"
}
}
}

Example prompts:

  • "Run the StreetEasy listing monitor for 20 Brooklyn rentals and summarize median asking rent."
  • "Snapshot 50 Manhattan sale listings and group them by broker."
  • "Run my Manhattan sale monitor and show only price or status changes."

MCP calls use your configured Apify identity and consume the same event pricing as Console or API runs.

Responsible use and legality

This Actor accesses public listing information without logging in.

You are responsible for following StreetEasy terms, Apify policies, applicable database rights, and privacy laws.

Use reasonable schedules and limits.

Do not use the output for harassment, discriminatory housing decisions, unsolicited contact, or attempts to identify private individuals.

Do not assume a public listing is error-free or independently verified.

StreetEasy and its marks belong to their respective owners.

This Actor is an independent tool and is not affiliated with StreetEasy or Zillow Group.

Troubleshooting

Why did the run fail with a blocked-session error?

The source challenged all three bounded US residential sessions.

Wait before retrying and inspect the run log.

Repeated immediate runs can increase challenge rates.

Why are no removed records present?

Removal detection requires a prior state and a complete current snapshot.

Increase maxItems or maxPages until the run is not truncated.

Why is daysOnMarket null or unexpectedly small?

It depends on StreetEasy's current createdAt value.

Relisted inventory may have a new source listing identity and creation time.

Why are unchanged records missing?

Monitoring defaults to a compact change feed.

Set emitUnchanged to true when you need a complete output on every run.

Can I use a listing detail URL as input?

No.

This Actor snapshots supported NYC or borough sale/rental search URLs.

Choose one source-specific Actor per marketplace instead of treating records from different platforms as equivalent listings.

Frequently asked questions

Is this a live alerting service?

No.

It produces snapshots and comparison records when a run starts.

Use Apify Schedules and webhooks to create alerts at your chosen interval.

Does it support sales and rentals in one run?

Yes.

Add multiple supported for-sale and for-rent URLs to startUrls.

Does it expose a StreetEasy API?

It exposes normalized results through the standard Apify API, datasets, clients, and MCP integration.

It does not provide credentials or privileged access to a private StreetEasy API.

Does monitoring preserve full history?

The dataset for each run is immutable according to your Apify retention settings.

The private monitor state stores the latest comparison values, not an unlimited event history.

Persist datasets to your warehouse when you need long-term history.