Discover/Apartments API
live

Apartments APIapartments.com

Search apartment listings, get unit-level pricing and amenities, and look up properties by management company via the Apartments.com API.

Endpoints
3
Updated
2mo ago

What is the Apartments API?

The Apartments.com API exposes 3 endpoints covering listing search, property details, and management company lookup across thousands of rental properties. Use search_properties to query by city name or lat/lng coordinates with bedroom and rent filters, get_property_details to retrieve unit-level floorplans, amenities, photos, and resident reviews for a specific listing, and get_management_companies to find all properties operated by a named company in a given market.

Try it
Latitude for coordinate-based search. Must be provided together with lng.
Longitude for coordinate-based search. Must be provided together with lat.
Page number for pagination.
Location search query (e.g., 'New York, NY', 'Sunnyvale, CA'). Either query or lat+lng required.
Search radius in miles when using lat/lng search.
Maximum number of bedrooms.
Maximum monthly rent filter.
Minimum number of bedrooms.
Minimum monthly rent filter.
Minimum square footage.
api.parse.bot/scraper/623cb755-df0e-49e0-ae8b-63558585a1c2/<endpoint>
Ready to send
Fill in the parameters and hit sign in to send to see live response data here.
Call it over HTTPgrab a free API key at signup
curl -X GET 'https://api.parse.bot/scraper/623cb755-df0e-49e0-ae8b-63558585a1c2/search_properties?query=New+York%2C+NY' \
  -H 'X-API-Key: $PARSE_API_KEY'
Python SDK · recommended

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 apartments-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.

"""
Apartments.com Parse API Client
Search apartment listings, get property details, and find properties by management company.
Get your API key from: https://parse.bot/settings
"""

import os
import requests
from typing import Any, Dict, List, Optional


class ParseClient:
    """Client for interacting with the Apartments.com Parse API."""

    def __init__(self, api_key: Optional[str] = None):
        """
        Initialize the Parse API client.
        
        Args:
            api_key: API key for authentication. If not provided, reads from PARSE_API_KEY env var.
            
        Raises:
            ValueError: If API key is not provided or found in environment.
        """
        self.base_url = "https://api.parse.bot"
        self.scraper_id = "623cb755-df0e-49e0-ae8b-63558585a1c2"
        self.api_key = api_key or os.getenv("PARSE_API_KEY")
        
        if not self.api_key:
            raise ValueError("API key must be provided or set in PARSE_API_KEY environment variable")

    def _call(self, endpoint: str, method: str = "POST", **params) -> Dict[str, Any]:
        """
        Make an API call to the Parse Bot endpoint.
        
        Args:
            endpoint: The endpoint name (e.g., 'search_properties')
            method: HTTP method ('GET' or 'POST')
            **params: Query/body parameters for the request
            
        Returns:
            Response JSON as dictionary
            
        Raises:
            requests.RequestException: If the API call fails
        """
        url = f"{self.base_url}/scraper/{self.scraper_id}/{endpoint}"
        headers = {
            "X-API-Key": self.api_key,
            "Content-Type": "application/json"
        }
        
        if method.upper() == "GET":
            response = requests.get(url, headers=headers, params=params)
        elif method.upper() == "POST":
            response = requests.post(url, headers=headers, json=params)
        else:
            raise ValueError(f"Unsupported HTTP method: {method}")
        
        response.raise_for_status()
        return response.json()

    def search_properties(
        self,
        query: Optional[str] = None,
        lat: Optional[float] = None,
        lng: Optional[float] = None,
        radius: float = 5,
        min_rent: Optional[int] = None,
        max_rent: Optional[int] = None,
        min_beds: Optional[int] = None,
        max_beds: Optional[int] = None,
        min_sqft: Optional[int] = None,
        page: int = 1
    ) -> Dict[str, Any]:
        """
        Search for apartment listings by city, region, or coordinates.
        
        Either query or lat+lng must be provided.
        
        Args:
            query: Search query (e.g., 'Sunnyvale, CA', 'Boston, MA')
            lat: Latitude for coordinate-based search
            lng: Longitude for coordinate-based search
            radius: Search radius in miles (default: 5)
            min_rent: Minimum rent amount
            max_rent: Maximum rent amount
            min_beds: Minimum number of bedrooms
            max_beds: Maximum number of bedrooms
            min_sqft: Minimum square footage
            page: Page number for pagination (default: 1)
            
        Returns:
            Dictionary with 'total_count', 'page', 'next_page_url', and 'properties' list
        """
        params = {
            k: v for k, v in {
                "query": query,
                "lat": lat,
                "lng": lng,
                "radius": radius,
                "min_rent": min_rent,
                "max_rent": max_rent,
                "min_beds": min_beds,
                "max_beds": max_beds,
                "min_sqft": min_sqft,
                "page": page
            }.items() if v is not None
        }
        return self._call("search_properties", method="GET", **params)

    def get_property_details(self, url: str) -> Dict[str, Any]:
        """
        Get detailed information for a specific property listing.
        
        Args:
            url: Full URL or relative path of the property page
            
        Returns:
            Dictionary with property details including amenities, units, photos, reviews, etc.
        """
        return self._call("get_property_details", method="GET", url=url)

    def get_management_companies(
        self,
        company_name: str,
        market: Optional[str] = None
    ) -> Dict[str, Any]:
        """
        Search for properties managed by a specific company in a market.
        
        Args:
            company_name: Name of the management company (e.g., 'Bozzuto', 'Greystar')
            market: Market name (e.g., 'Boston'). If omitted, searches US-wide.
            
        Returns:
            Dictionary with 'total_count' and 'properties' list
        """
        params = {"company_name": company_name}
        if market:
            params["market"] = market
        return self._call("get_management_companies", method="GET", **params)


def extract_price(price_str: str) -> int:
    """Extract numeric value from price string."""
    try:
        return int(price_str.replace("$", "").replace(",", "").split("-")[0].strip())
    except (ValueError, IndexError):
        return 0


def main():
    """
    Practical workflow: Search for apartments, get details for promising results,
    and identify management companies to contact.
    """
    
    # Initialize client
    client = ParseClient()
    
    print("=" * 90)
    print("APARTMENT HUNTING WORKFLOW - PARSE API DEMO")
    print("=" * 90)
    
    # Step 1: Search for apartments with specific criteria
    print("\n[STEP 1] Searching for apartments...")
    print("         Location: San Francisco, CA")
    print("         Criteria: $3000-$5500/month, 1-2 bedrooms, min 600 sqft\n")
    
    search_results = client.search_properties(
        query="San Francisco, CA",
        min_rent=3000,
        max_rent=5500,
        min_beds=1,
        max_beds=2,
        min_sqft=600,
        page=1
    )
    
    total_found = search_results.get("total_count", 0)
    properties = search_results.get("properties", [])
    current_page = search_results.get("page", 1)
    next_page_url = search_results.get("next_page_url")
    
    print(f"✓ Found {total_found} properties matching criteria")
    print(f"  Displaying page {current_page} with {len(properties)} results")
    if next_page_url:
        print(f"  More results available on next page")
    
    if not properties:
        print("No properties found. Exiting.")
        return
    
    # Display search results summary
    print("\n" + "-" * 90)
    print("TOP SEARCH RESULTS")
    print("-" * 90)
    
    for idx, prop in enumerate(properties[:5], 1):
        listing_id = prop.get("listing_id", "N/A")
        name = prop.get("name", "Unknown")
        address = prop.get("address", "N/A")
        price_range = prop.get("price_range", "N/A")
        beds = prop.get("beds", "N/A")
        phone = prop.get("phone", "Contact for info")
        
        print(f"\n{idx}. {name}")
        print(f"   ID: {listing_id}")
        print(f"   Address: {address}")
        print(f"   Bedrooms: {beds} | Price: {price_range}")
        print(f"   Contact: {phone}")
    
    # Step 2: Get detailed information for top properties
    print("\n" + "=" * 90)
    print("DETAILED PROPERTY ANALYSIS")
    print("=" * 90)
    
    management_companies_found = {}
    detailed_properties = []
    
    for idx, prop in enumerate(properties[:3], 1):
        prop_url = prop.get("url")
        prop_name = prop.get("name", "Unknown Property")
        
        if not prop_url:
            print(f"\n[Property {idx}] ⚠ No URL available, skipping...")
            continue
        
        print(f"\n[Property {idx}] Fetching details for {prop_name}...")
        
        try:
            details = client.get_property_details(prop_url)
            detailed_properties.append(details)
            
            address = details.get("address", "N/A")
            management = details.get("management_company", "Not specified")
            neighborhood = details.get("neighborhood", "N/A")
            pricing_summary = details.get("pricing_summary", "N/A")
            has_ev = details.get("has_ev_charging", False)
            total_units = details.get("total_units_count", 0)
            
            print(f"  ✓ Details retrieved successfully")
            print(f"    Neighborhood: {neighborhood}")
            print(f"    Pricing: {pricing_summary}")
            print(f"    Management: {management}")
            print(f"    Total Units Available: {total_units}")
            print(f"    EV Charging: {'Yes ⚡' if has_ev else 'No'}")
            
            # Track management companies
            if management and management != "Not specified":
                if management not in management_companies_found:
                    management_companies_found[management] = []
                management_companies_found[management].append(prop_name)
            
            # Display amenities
            amenities = details.get("amenities", [])
            if amenities:
                display_amenities = amenities[:5]
                print(f"    Amenities: {', '.join(display_amenities)}", end="")
                if len(amenities) > 5:
                    print(f" + {len(amenities) - 5} more")
                else:
                    print()
            
            # Display pet policy
            pet_policy = details.get("pet_policy", [])
            if pet_policy:
                print(f"    Pet Policy: {', '.join(pet_policy)}")
            else:
                print(f"    Pet Policy: No information available")
            
            # Display unit details
            units = details.get("units", [])
            if units:
                sorted_units = sorted(
                    units,
                    key=lambda u: extract_price(u.get("price", "$0"))
                )
                
                print(f"    Sample Units (showing {min(3, len(sorted_units))} of {len(units)}):") 
                for unit in sorted_units[:3]:
                    beds = unit.get("beds", "?")
                    baths = unit.get("baths", "?")
                    price = unit.get("price", "Call for price")
                    sqft = unit.get("sqft", "?")
                    availability = unit.get("availability", "Contact")
                    
                    print(f"      • {beds}BR/{baths}BA - {price} ({sqft} sqft) - {availability}")
            
            # Display reviews
            reviews = details.get("reviews", [])
            if reviews and reviews[0].get("rating"):
                latest = reviews[0]
                rating = latest.get("rating", "N/A")
                title = latest.get("title", "No title")
                print(f"    Latest Review: ⭐ {rating}/5 - {title}")
            
        except Exception as e:
            print(f"  ✗ Error fetching details: {str(e)}")
    
    # Step 3: Search for properties by management company
    print("\n" + "=" * 90)
    print("MANAGEMENT COMPANY PORTFOLIO")
    print("=" * 90)
    
    if management_companies_found:
        print(f"\nFound {len(management_companies_found)} management company/companies:\n")
        
        for company_name in list(management_companies_found.keys())[:2]:
            properties_in_results = management_companies_found[company_name]
            print(f"[Company] {company_name}")
            print(f"  Properties in search results: {', '.join(properties_in_results)}")
            
            print(f"  Searching all {company_name} properties in San Francisco...")
            
            try:
                company_results = client.get_management_companies(
                    company_name=company_name,
                    market="San Francisco, CA"
                )
                
                total_company_props = company_results.get("total_count", 0)
                company_props = company_results.get("properties", [])
                
                print(f"  ✓ Found {total_company_props} total properties managed by {company_name}")
                
                if company_props:
                    print(f"  Showing {min(3, len(company_props))} additional properties:")
                    for prop in company_props[:3]:
                        prop_name = prop.get("name", "N/A")
                        prop_phone = prop.get("phone", "N/A")
                        print(f"    • {prop_name} - {prop_phone}")
                print()
                
            except Exception as e:
                print(f"  ✗ Error searching by company: {str(e)}\n")
    else:
        print("\nNo specific management companies found in detailed property results.")
        print("Try searching for individual companies using get_management_companies().")
    
    # Summary and recommendations
    print("=" * 90)
    print("SEARCH SUMMARY & RECOMMENDATIONS")
    print("=" * 90)
    
    print(f"\n📊 Statistics:")
    print(f"   • Total properties found: {total_found}")
    print(f"   • Properties analyzed in detail: {len(detailed_properties)}")
    print(f"   • Unique management companies: {len(management_companies_found)}")
    
    if detailed_properties:
        print(f"\n💡 Next Steps:")
        print(f"   1. Review the {len(detailed_properties)} detailed properties above")
        print(f"   2. Contact management companies directly for tours and current availability")
        print(f"   3. Use search_properties() with page=2 to see more listings")
        print(f"   4. Filter by management company to see their full portfolio")
    
    print(f"\n✓ Workflow complete!\n")


if __name__ == "__main__":
    main()
All endpoints · 3 totalmissing one? ·

Search for apartment listings by city, region, or coordinates with advanced filters. Returns up to 40 properties per page. Either query or lat+lng must be provided.

Input
ParamTypeDescription
latnumberLatitude for coordinate-based search. Must be provided together with lng.
lngnumberLongitude for coordinate-based search. Must be provided together with lat.
pageintegerPage number for pagination.
querystringLocation search query (e.g., 'New York, NY', 'Sunnyvale, CA'). Either query or lat+lng required.
radiusnumberSearch radius in miles when using lat/lng search.
max_bedsintegerMaximum number of bedrooms.
max_rentintegerMaximum monthly rent filter.
min_bedsintegerMinimum number of bedrooms.
min_rentintegerMinimum monthly rent filter.
min_sqftintegerMinimum square footage.
Response
{
  "type": "object",
  "fields": {
    "page": "integer current page number",
    "properties": "array of property objects with listing_id, property_id, url, name, address, price_range, beds, phone",
    "total_count": "integer total number of matching listings",
    "next_page_url": "string URL of the next page or null if no more pages"
  },
  "sample": {
    "data": {
      "page": 1,
      "properties": [
        {
          "url": "https://www.apartments.com/10-halletts-point-astoria-ny/1j2c5h6/",
          "name": "10 Halletts Point, Astoria, NY",
          "phone": "+1 (555) 012-3456",
          "address": "10, 20, 30 Halletts Pt, Astoria, NY 11102",
          "listing_id": "1j2c5h6",
          "property_id": null
        }
      ],
      "total_count": 700,
      "next_page_url": "https://www.apartments.com/new-york-ny/2/"
    },
    "status": "success"
  }
}

About the Apartments API

Search and Filter Listings

The search_properties endpoint accepts either a text query (e.g., "Austin, TX") or a lat/lng pair with an optional radius in miles. Results return up to 40 properties per page, each object carrying listing_id, property_id, name, address, price_range, beds, phone, and a direct url. Pagination is handled via the page parameter; the response also includes total_count and a next_page_url field so you can walk through large result sets programmatically. Narrow results further with min_beds, max_beds, and max_rent filters.

Property Detail Data

get_property_details takes a full property URL and returns a structured object with an array of units, each containing floorplan, unit_number, price, max_rent, sqft, availability, beds, and baths. Beyond unit data, the response includes amenities (array of strings), pet_policy, a photos array of image URLs, neighborhood, and a reviews array where each entry has title, rating, text, and date. This makes it possible to surface resident sentiment alongside pricing in a single call.

Management Company Lookup

get_management_companies accepts a company_name (e.g., "Greystar" or "Bozzuto") and an optional market string. When market is omitted, the search covers the entire US. The response mirrors the structure of the search endpoint — a properties array with the same listing fields — plus total_count and the echoed company_name and market values. This is useful for portfolio analysis, competitive research, or tracking which markets a specific operator is active in.

Reliability & maintenance

The Apartments API is a managed, monitored endpoint for apartments.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when apartments.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 apartments.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?+
It's built not to. Every endpoint is health-checked on a schedule with automated test probes. When the source site changes and a check fails, the API is automatically queued for repair and re-verified — that's the self-healing layer. Each API page shows when its endpoints were last verified. And because marketplace APIs are shared, any fix reaches everyone using it.
Is this an official API from the source site?+
No — Parse APIs are independent, managed REST wrappers over publicly available data. That is the point: where a site has no official API (or only a limited one), Parse gives you a maintained, monitored endpoint for that data and keeps it working as the site changes — so you get a stable contract over a source that never promised one.
Can I fix or extend this API myself if I need a new endpoint or field?+
Yes — and you don't have to wait on us. This API was generated by the Parse agent, which stays attached. Describe the change in plain English ("add an endpoint that returns reviews", "fix the price field") in the revise box on the API page or via the revise_api MCP tool, and the agent rebuilds it against the live site in minutes. Contributing the change back to the public API is free.
What happens if I call an endpoint that has an issue?+
Errors are machine-readable: a bad call returns a clean status with the list of available endpoints and a repair hint, so an agent (or you) can recover or trigger a fix instead of failing silently. Confirmed failures feed the automatic repair queue.
Common use cases
  • Aggregate current rent ranges by neighborhood using search_properties with coordinate-based queries across a metro area.
  • Build a unit availability tracker that polls get_property_details and alerts when a specific floorplan opens or changes price.
  • Map management company footprints by calling get_management_companies for major operators across multiple markets.
  • Compare reviews ratings across competing properties in the same ZIP code to surface resident satisfaction signals.
  • Populate a relocation tool with amenities, pet_policy, and photos pulled from get_property_details.
  • Estimate market-rate rents for a given bedroom count by filtering search_properties results with min_beds and max_beds.
  • Monitor portfolio concentration by tracking how many listings a company holds per market via get_management_companies.
Pricing & limitsSee full pricing →
TierPriceCredits/monthRate limit
Free$0/mo1005 req/min
Hobby$30/mo1,00020 req/min
Developer$100/mo5,000100 req/min

One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.

Frequently asked questions
Does Apartments.com have an official developer API?+
Apartments.com does not publish a public developer API or documented data feed for third-party use. This Parse API provides structured access to the listing data available on the site.
How does pagination work in `search_properties`?+
Each response returns up to 40 properties and includes a total_count integer and a next_page_url string. Pass the page parameter to retrieve subsequent pages. When next_page_url is null, you have reached the last page of results.
What unit-level fields does `get_property_details` return?+
Each object in the units array includes floorplan, unit_number, price, max_rent, sqft, availability, beds, and baths. The endpoint also returns amenities, pet_policy, photos, neighborhood, and a reviews array with per-review rating, title, text, and date.
Can I filter search results by amenities or property type (e.g., only condos or pet-friendly buildings)?+
The current search_properties endpoint supports filters for min_beds, max_beds, max_rent, and location. Amenity-level or property-type filters are not available as parameters. You can fork this API on Parse and revise it to add those filter parameters.
Does the API cover room-for-rent or sublet listings?+
The API covers standard apartment listings indexed on Apartments.com, including unit-level details and management company data. Room-for-rent and sublet listings are not currently exposed as a distinct category. You can fork the API on Parse and revise it to target that listing segment if it appears in the source data.
Page content last updated . Spec covers 3 endpoints from apartments.com.
Related APIs in Real EstateSee all →
rent.com API
Browse and extract rental property data from Rent.com. Search listings by location and filter by beds, baths, price, and pet policy. Retrieve full property details, floor plans, unit availability, amenities, nearby schools, points of interest, and active specials.
realtor.com API
Search millions of real estate listings on Realtor.com, view detailed property information, find qualified agents in your area, and access market analytics to understand pricing trends. Get location suggestions and property insights all in one place to help you make informed decisions about buying, selling, or investing in real estate.
Craigslist Apartments API
Search and filter Craigslist apartment listings by neighborhood, bedroom count, price range, and image availability. Retrieve detailed listing information including full descriptions, contact details, photos, and location data.
rentals.ca API
Search and browse rental listings across Canada by city or neighbourhood, and view detailed property information including prices, amenities, and availability. Find your next home by filtering thousands of rental properties on Rentals.ca in real-time.
streeteasy.com API
Search and browse NYC apartment rentals to find detailed property information including photos, amenities, pricing, and direct contact details for brokers and agents. Filter through available listings and access comprehensive rental data to help you discover your next home in New York City.
padmapper.com API
Search and browse rental listings across cities with detailed property information including prices, contact details, and market trends. Discover apartments and homes through city-wide searches or map-based exploration, and access comprehensive listing details to help you find your next rental.
inberlinwohnen.de API
Search and browse affordable apartment listings from Berlin's state-owned housing companies, view detailed property information, and access company profiles and tenant guides. Find your next home in Berlin with comprehensive data on available rentals and housing provider information in one place.
inmuebles.mercadolibre.com.ar API
Search and browse apartment listings on Mercado Libre Argentina with detailed information including prices, addresses, and full descriptions. Get access to paginated results to easily explore available properties across different areas.