StreetEasy $1๐Ÿ’ฐ URL Search | Keyword Filtering | Rich Output avatar

StreetEasy $1๐Ÿ’ฐ URL Search | Keyword Filtering | Rich Output

Pricing

from $1.00 / 1,000 results

Go to Apify Store
StreetEasy $1๐Ÿ’ฐ URL Search | Keyword Filtering | Rich Output

StreetEasy $1๐Ÿ’ฐ URL Search | Keyword Filtering | Rich Output

From $1/1K. Scrape streeteasy.com across NYC and Jersey City for sales, rentals, in-contract, and sold properties. Supports filters or direct URLs. Returns pricing, coordinates, photos, brokerage, amenities, building details, agent contacts, and price history.

Pricing

from $1.00 / 1,000 results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

18

Total users

4

Monthly active users

1.8 hours

Issues response

4 days ago

Last modified

Share

StreetEasy NYC Scraper

Pull complete NYC and Jersey City listings from StreetEasy: for-sale, for-rent, in-contract, and recently sold. Combine filters (areas, price, beds, baths, sqft, amenities, sort) into a single search, or paste any StreetEasy URL and let the actor walk pagination forward. Returns 30+ fields per listing including coordinates, neighborhood, brokerage, photos, and optional detail-page enrichment for amenities, building info, agent contact, and price history.

Why This Scraper?

  • Structured filter mode covering price, beds, baths, sqft, amenities, sort, and 5 listing categories (sale, rent, in contract, sold, off market).
  • Returns up to 500 listings per page, so a 100-result run completes in seconds.
  • Coordinates (latitude / longitude) on every record without needing detail enrichment.
  • Auto-expand mode splits queries above ~1,050 results into price buckets so you can extract the full market.
  • URL mode accepts any sale, rent, sold, building, or filtered StreetEasy URL.
  • Pay-per-result pricing: low base rate; detail enrichment surcharge fires only when you turn it on, only for records that actually returned detail.
  • All five NYC boroughs plus Jersey City, Hoboken, and surrounding NJ areas.
  • Optional incremental mode for recurring/scheduled monitoring: run the same search daily or weekly and get back only what's new, changed, reappeared, or gone.

Data You Get

Sample shape, values are illustrative placeholders, not from a live listing.

FieldExample
id0000001
urlhttps://streeteasy.com/building/sample-tower/4a
saleTypeforSale
statusFor sale
price1250000
neighborhoodSample Neighborhood
boroughManhattan
address100 Sample Street
unit4A
bedrooms2
bathrooms2
halfBathrooms0
squareFeet1100
pricePerSqft1136.36
propertyTypeCondo
latitude40.7000
longitude-74.0000
imageUrlhttps://photos.zillowstatic.com/fp/0-uncropped.webp
brokerageSample Realty
listedAt2026-01-01
daysOnMarket30
advertisedListingfalse
description(when fetchDetails = true) Full listing description
amenities["Doorman", "Elevator", "Gym"]
buildingNameSample Tower
buildingYear1990
schoolDistricts["1"]
transit["6", "Q"]
priceHistory[{date,event,price}, ...]
agents[{name,phone,brokerage}, ...]
openHouseDates["2026-02-01"]

How to Use

Search mode, single borough:

{
"mode": "search",
"saleType": "forSale",
"locations": ["manhattan"],
"minPrice": 1000000,
"maxPrice": 2000000,
"minBedrooms": 2,
"amenities": ["DOORMAN", "ELEVATOR"],
"sortBy": "PRICE_ASC",
"maxPages": 5,
"maxListings": 200
}

Search mode, multi-borough rentals:

{
"mode": "search",
"saleType": "forRent",
"locations": ["brooklyn", "queens"],
"maxPrice": 4000,
"noFee": true,
"minBedrooms": 1,
"sortBy": "LISTED_AT_DESC",
"maxListings": 100
}

URL mode, multi-URL:

{
"mode": "url",
"urls": [
"https://streeteasy.com/for-sale/williamsburg",
"https://streeteasy.com/for-rent/upper-east-side?page=2",
"https://streeteasy.com/sold/manhattan"
],
"maxPages": 3,
"perPage": 200
}

Detail enrichment (slower, full agent + amenity coverage):

{
"mode": "search",
"saleType": "forSale",
"locations": ["dumbo"],
"fetchDetails": true,
"maxListings": 25
}

Input Parameters

ParameterTypeDefaultDescription
modeenumsearchsearch (filters) or url (paste URLs).
saleTypeenumforSaleforSale, forRent, inContract, recentlySold, offMarket.
locationsstring[]["nyc"]Slugs (manhattan, brooklyn, williamsburg, jersey-city, ...) or numeric IDs.
propertyTypesenum[][]CONDO, CO_OP, HOUSE, TOWNHOUSE, MULTI_FAMILY, RENTAL, CONDOP.
minPrice / maxPriceintegernonePrice range in USD.
minBedroomsintegernoneUse 0 for studios.
maxBedroomsintegernone
minBathroomsnumbernoneDecimal supported (1.5).
minSqft / maxSqftintegernoneLiving area in square feet.
amenitiesenum[][]Listings must include all selected amenities.
noFeebooleanfalseRentals only: filter to no-broker-fee listings.
keywordsstringnoneFree-text search inside the description / title.
sortByenumRECOMMENDEDRECOMMENDED, PRICE_ASC/DESC, LISTED_AT_ASC/DESC, SQFT_DESC, BEDROOMS_DESC.
urlsstring[][]URL mode only.
maxPagesinteger0 (unlimited)Pagination cap per query. Leave empty to walk every result page until exhausted (bounded only by maxListings).
perPageinteger100Listings per page (10 to 500).
maxListingsinteger20Hard cap across the whole run, 0 means unlimited. Bump for production scrapes.
fetchDetailsbooleanfalseEnrich each record with detail page fields. Adds 1 HTTP request per record.
expandLargeQueriesbooleanfalseAuto-shard queries above 1,050 results into price buckets and merge.
proxyobjectApify Residential USCountry forced to US.
resumeFromRunIdstringnonePrevious run ID or dataset ID to continue a full-catalogue walk across separate runs. Listings already saved there (matched by listing id) are skipped.
incrementalModebooleanfalseRecurring/scheduled monitoring of the SAME search. Off by default so no existing run changes until you opt in.
stateKeystringnone (auto)Incremental mode only. Names a monitoring campaign, or deliberately shares state across differently-configured runs. Leave empty to auto-derive one from the search scope.
emitUnchangedbooleanfalseIncremental mode only. Also return listings unchanged since the last run, marked UNCHANGED. Returns and bills extra rows.
emitExpiredbooleanfalseIncremental mode only. Also return listings no longer found, marked EXPIRED โ€” only after a complete scan (not when Max listings/Max pages capped the run, the site blocked a page, or Resume was used). Returns and bills extra rows.

For an unbounded pull (maxPages left empty, maxListings: 0), resumeFromRunId lets you continue in a brand-new run: paste the ID of a previous run (or its dataset), and this run skips every listing id already saved there, appending only new listings. The actor also checkpoints its dedup set to the key-value store periodically, so a platform migration or restart mid-run resumes without re-scraping (and re-charging) already-saved listings.

Resume and recurring updates

Two different things, both under the same input section:

  • resumeFromRunId continues one specific interrupted run (or grows one big catalogue pull across separate runs). It does not remember anything about the search itself โ€” you paste the previous run/dataset id each time.
  • incrementalMode is for running the same search again and again (daily, weekly โ€” on a schedule) and getting back only what changed. Turn it on and the actor remembers the previous run of that search itself, keyed by stateKey (or an automatic key derived from your search scope โ€” locations/URLs, filters, and fetchDetails). Every emitted row then carries changeType (NEW / UPDATED / REAPPEARED / EXPIRED / UNCHANGED), changedFields, firstSeenAt, and lastSeenAt.
    • By default only NEW, UPDATED, and REAPPEARED listings are returned โ€” unchanged listings are skipped and not billed.
    • Turn on emitUnchanged to also get UNCHANGED rows back (billed like any other row).
    • Turn on emitExpired to also get a synthetic EXPIRED row for a listing that dropped out of the tracked search โ€” but only once a run has proven a complete scan (Max listings/Max pages didn't cap it, the site didn't block a page mid-walk, and Resume wasn't used). A partial run never marks anything expired; it just keeps last run's state as-is.
    • Two differently-configured searches (different locations, filters, or fetchDetails) never share a baseline unless you set the same stateKey on purpose.
    • incrementalMode and resumeFromRunId are normally not combined. If you turn both on against a search that already has saved incremental state, the run fails fast with a clear message instead of silently mixing the two. Combining them only makes sense to bootstrap a brand-new monitoring campaign from an existing catalogue pull โ€” see the schema field descriptions for details.
    • Detail-enrichment billing is unaffected by suppression: an UNCHANGED row that gets skipped was never charged the detail-enrichment surcharge either, even though its detail page still had to be fetched to check whether it changed.
{
"mode": "search",
"saleType": "forSale",
"locations": ["park-slope"],
"incrementalMode": true,
"stateKey": "park-slope-daily",
"maxListings": 0
}

Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape โ€” the Apify dataset is never changed.

What gets written to the connector: a condensed, human-readable summary of each record โ€” not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify โ†’ Settings โ†’ Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
  3. For Notion, also set notionParentPageUrl to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

Output Example

Sample shape, values are illustrative placeholders.

{
"id": "0000001",
"url": "https://streeteasy.com/building/sample-tower/4a",
"saleType": "forSale",
"status": "For sale",
"price": 1250000,
"neighborhood": "Sample Neighborhood",
"borough": "Manhattan",
"address": "100 Sample Street",
"unit": "4A",
"bedrooms": 2,
"bathrooms": 2,
"halfBathrooms": 0,
"squareFeet": 1100,
"pricePerSqft": 1136.36,
"propertyType": "Condo",
"latitude": 40.7000,
"longitude": -74.0000,
"imageUrl": "https://photos.zillowstatic.com/fp/0-uncropped.webp",
"images": ["https://photos.zillowstatic.com/fp/0-uncropped.webp"],
"brokerage": "Sample Realty",
"listedAt": "2026-01-01",
"daysOnMarket": 30,
"offMarketAt": null,
"furnished": false,
"noFee": null,
"advertisedListing": false,
"description": "Full seller description text appears here when fetchDetails = true.",
"amenities": ["Doorman", "Elevator", "Gym"],
"buildingName": "Sample Tower",
"buildingYear": 1990,
"schoolDistricts": ["1"],
"transit": ["6", "Q"],
"priceHistory": [{ "date": "2026-01-01", "event": "Listed", "price": 1250000 }],
"agents": [{ "name": "Agent Name", "phone": "+10000000000", "brokerage": "Sample Realty" }],
"openHouseDates": ["2026-02-01"],
"virtualTourUrl": null,
"sourceUrl": null
}

With incrementalMode: true, every row additionally carries:

{
"changeType": "UPDATED",
"changedFields": ["price", "status"],
"firstSeenAt": "2026-06-01T00:00:00.000Z",
"lastSeenAt": "2026-07-29T00:00:00.000Z"
}

changeType is one of NEW / UPDATED / REAPPEARED / UNCHANGED (only when emitUnchanged is on) / EXPIRED (only when emitExpired is on). These four fields are absent entirely when incrementalMode is off โ€” the default output shape is unchanged.

Plan Requirement

This actor requires Apify Residential proxy with country US. StreetEasy blocks datacenter ranges, so the default Apify proxy (datacenter) will return 0 results.

  • Free plan: does not include Residential proxy. Upgrade to Starter or higher.
  • Starter plan and above: includes Residential proxy access.
  • The actor automatically pins country to US even if you forget to select it.

If you run on Free plan with the default proxy, you will see a prominent warning at the start of the run and an empty dataset. Upgrade and re-run.