Brownstone NYC APIbrownstonenyc.com ↗
Access Brownstone NYC case study data: property names, headlines, descriptions, photos, and YouTube videos for renovated Brooklyn buildings via 2 endpoints.
What is the Brownstone NYC API?
The Brownstone NYC API exposes 2 endpoints that return structured data from the property project pages published in Brownstone NYC's Case Study menu. Use search_properties to list all published projects with names, headlines, narrative descriptions, photo URLs, and YouTube video URLs, or use get_property to fetch a single project by slug. Each record includes up to 7 fields covering the full public content of a project page.
curl -X GET 'https://api.parse.bot/scraper/cbeb1d9b-ccec-42ca-9233-2a893c9b44cf/search_properties?query=brooklyn' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace brownstonenyc-com-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: Brownstone NYC Properties API — browse renovation case studies."""
from parse_apis.brownstonenyc_com_api import BrownstoneNYC, PropertyNotFound
client = BrownstoneNYC()
# List all published property projects (currently a small catalogue).
for prop in client.properties.search(limit=10):
print(prop.name, "-", prop.headline, "|", len(prop.images), "photos")
# Drill into the first Brooklyn-related property via keyword search.
hit = client.properties.search(query="brooklyn", limit=1).first()
if hit is not None:
# Fetch the full detail record using the slug discovered above.
detail = client.properties.get(slug=hit.slug)
print(detail.name, detail.url)
if detail.videos:
print(" video:", detail.videos[0])
# Refresh to confirm the record is still current.
refreshed = detail.refresh()
print("refreshed:", refreshed.name)
# Demonstrate typed error handling on a bad slug.
try:
client.properties.get(slug="nonexistent-property")
except PropertyNotFound:
print("property not found — expected for an unknown slug")
print("exercised: properties.search / properties.get / refresh / PropertyNotFound")
Lists every property project page published in the site's Case Study menu and returns one record per property (slug, name, headline, narrative description, photo URLs, YouTube video URLs, page URL). Each call reads the site navigation plus one page per property (currently 5 pages, capped at 20), so it costs a handful of round trips. An optional free-text query filters the records locally by case-insensitive substring match over name, menu label, headline and description; an unmatched query returns an empty properties array with success. total_listed is the number of properties the site menu lists before filtering; returned is the count after filtering; failed_pages names any property page that could not be read. No pagination.
| Param | Type | Description |
|---|---|---|
| query | string | Free-text keyword matched case-insensitively against property name, headline and description (e.g. a neighborhood such as brooklyn). Omitted = all properties. |
{
"type": "object",
"fields": {
"query": "the applied keyword filter, or null when none",
"returned": "integer count of records after filtering",
"properties": "array of property records: slug (page identifier usable with get_property), name, headline, description, images (array of photo URLs), videos (array of YouTube URLs), url, menu_label",
"failed_pages": "array of {slug, status_code} for property pages that could not be read",
"total_listed": "integer count of properties in the site menu before filtering"
},
"sample": {
"data": {
"query": null,
"returned": 5,
"properties": [
{
"url": "https://brownstonenyc.com/45-plaza/",
"name": "45 Plaza",
"slug": "45-plaza",
"images": [
"https://i0.wp.com/brownstonenyc.com/wp-content/uploads/2022/11/image0011q.jpg?fit=840%2C840&ssl=1"
],
"videos": [
"https://youtu.be/wkPofgWCO-U"
],
"headline": "Plaza",
"menu_label": "Plaza",
"description": "In the center of Park Slope Brownstone NYC's sister company, Hub Renovations, contracted a one bedroom renovation in the coop apartment building of 45 Plaza West."
}
],
"failed_pages": [],
"total_listed": 5
},
"status": "success"
}
}About the Brownstone NYC API
Endpoints and Coverage
The API covers the property renovation and acquisition case studies that Brownstone NYC publishes publicly. search_properties reads the site's Case Study navigation and returns one record per property, currently spanning 5 project pages. Each record includes a slug, name, headline, description, an images array of photo URLs, a videos array of YouTube video URLs, and the url of the source page. The response also reports total_listed (count before filtering) and returned (count after filtering), plus a failed_pages array for any pages that could not be read.
Filtering and Lookup
search_properties accepts an optional query string that is matched case-insensitively against the property name, headline, and description. This lets you narrow results to a neighborhood name, architectural term, or project keyword without fetching and comparing records yourself. The applied filter value is echoed back in the response as query, or null when no filter was passed.
Single-Property Detail
get_property takes a slug exactly as emitted by search_properties and returns the full record for that one property in a single round trip. All fields are identical to the search response: url, name, slug, images, videos, headline, and description. If the slug does not match a current page on the site, the endpoint returns a stale_input / input_not_found error rather than an empty result, so callers can distinguish a bad input from an empty dataset.
Data Shape Notes
headline and description are nullable — the API returns null for either field when the source page does not include that content. images and videos are always arrays and may be empty. Photo URLs and YouTube video URLs are returned as-is from the published pages, so they remain stable as long as the source page is unchanged.
The Brownstone NYC API is a managed, monitored endpoint for brownstonenyc.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when brownstonenyc.com changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official brownstonenyc.com API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Build a portfolio gallery of Brownstone NYC renovation projects using
imagesarrays fromsearch_properties. - Filter projects by Brooklyn neighborhood name using the
queryparam and display matchingheadlineanddescriptiontext. - Embed YouTube videos from the
videosfield into a real estate content site covering NYC brownstone renovations. - Monitor the
total_listedcount over time to detect when new case study pages are added to the site. - Use
get_propertywith a known slug to refresh a cached record for a specific project page. - Aggregate
descriptiontext across all projects to analyze renovation narratives and common project themes.
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 200 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
| Team | $300/mo | 20,000 | 300 req/min |
| Company | $1,000/mo | 100,000 | 500 req/min |
Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does Brownstone NYC provide an official developer API?+
What does `search_properties` return when I pass a `query` value?+
search_properties matches the query string case-insensitively against each property's name, headline, and description fields. Records that do not match are excluded. The response includes a returned integer for the filtered count and a total_listed integer for the unfiltered count, so you can tell how many projects were filtered out.How many properties does the API currently cover?+
total_listed field in search_properties always reports the live count. If a page fails to load, it appears in failed_pages with its slug and HTTP status_code rather than silently dropping from results.Does the API expose contact details, pricing, or availability for the properties?+
What happens if a property page is temporarily unavailable?+
search_properties call, that property is recorded in the failed_pages array with its slug and the status_code returned. It is excluded from the properties array and the returned count for that call, but the rest of the results are still returned normally.