Skip to content
Scrappa Get API key
Apartment List API 1 credit/request

Apartment List Rental Search API Documentation

GET https://scrappa.co/api/apartmentlist/search?location_id=642592&beds=2&price_max=1500&sort=price_asc&per_page=20

Scrappa's GET /api/apartmentlist/search returns Apartment List rentals in one United States location as structured JSON.

Rentals only, United States

Apartment List lists homes for rent. It has no sale listings, so this API has no sale parameter.

What you get

total is the number of matching properties and total_units the number of matching units. Each listing has rental_id, slug, url, name, address, neighborhood, geo, phone, bed_range, price_range, units_available, soonest_available, floorplans with their units (price, fees, size, move-in date, lease length, apply link), photos, amenities, rating, review_summary and sponsored flags. Call the listing endpoint for fees, pet policy, specials and the property manager.

Filters are honoured

Beds, baths and price are checked on every unit before it is returned. A unit that does not match your filter is never returned, and a property with no matching unit is left out and counted in meta.omitted, so a page can hold fewer than per_page listings. beds takes 0 for a studio and 3 for "3 or more", the way the site does. baths is a minimum. applied_filters echoes what was used.

Location

location_id is required. Take it from /api/apartmentlist/location-autocomplete. An unknown id returns 422 (unknown_location).

Sorting and sponsored listings

default is the site's freshness order, price_asc and price_desc sort by price, and best_match is the site's own ranking. Sponsored listings keep the position the site gives them and carry is_featured: true and a featured_tag. They are never moved or removed, so a price sort can show a sponsored listing out of order.

Pagination

page is 1-based and per_page is 1-48. The full result list is kept for two minutes per filter set, so a page stays the same while you page through it. A page past the last one returns an empty listings list with the real total. It never returns another page's listings.

Prices

Prices are numbers in US dollars. A hidden price is null, never 0.

Apartment List Rental Search API Documentation 1 credit/request

Endpoint

Request preview
GET
https://scrappa.co/api/apartmentlist/search?location_id=642592&beds=2&price_max=1500&sort=price_asc&per_page=20
Auth header
x-api-key
Cost
1 credit/request
location_id = 642592
Response preview
200 OK
{
    "success": true,
    "total": 357,
    "total_units": 4168,
    "returned": 1,
    "pagination": {
        "page": 1,
        "per_page": 20,
        "total_pages": 18,
        "has_next_page": true
    },
    "applied_filters": {
        "location_id": 642592,
        "beds": [
...

Parameters

Start with the required fields, then add optional filters only when your use case needs them.

Runnable path

1 required parameter needed before sending a request.

8 optional filters available.

location_id integer Required

Location id from location-autocomplete, for example 642592 for Austin, TX.

Example value 642592
beds string Optional

Bedroom counts: 0 (studio), 1, 2 or 3 (3 or more). Repeat the parameter or separate with commas.

Example value 2
baths string Optional

Minimum bathrooms: 1, 2 or 3.

Example value example
price_min integer Optional

Minimum monthly rent in US dollars, per unit.

Example value 10
price_max integer Optional

Maximum monthly rent in US dollars, per unit.

Example value 1500
amenities string Optional

Amenity keys such as is_dog_friendly, is_cat_friendly, has_pool, has_gym, has_parking or has_in_unit_laundry. Properties must have all of them. Unknown keys are rejected.

Example value example
sort string Optional

default (freshness), price_asc, price_desc or best_match.

Example value price_asc
page integer Optional

Result page, 1-based.

Example value 1
per_page integer Optional

Listings per page, 1-48 (default 20).

Example value 20

Request Examples

PHP
<?php

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => "https://scrappa.co/api/apartmentlist/search?location_id=642592&beds=2&price_max=1500&sort=price_asc&per_page=20",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => [
        "x-api-key: YOUR_API_KEY_HERE"
    ],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #:" . $err;
} else {
    echo $response;
}
PHP
<?php

use Illuminate\Support\Facades\Http;

$response = Http::timeout(30)
    ->withHeaders(['x-api-key' => 'YOUR_API_KEY_HERE'])
    ->get('https://scrappa.co/api/apartmentlist/search?location_id=642592&beds=2&price_max=1500&sort=price_asc&per_page=20');

if ($response->successful()) {
    echo $response->body();
} else {
    echo "Error: " . $response->status();
}
JavaScript
const options = {
    method: 'GET',
    headers: {
        'x-api-key': 'YOUR_API_KEY_HERE'
    }
};

fetch('https://scrappa.co/api/apartmentlist/search?location_id=642592&beds=2&price_max=1500&sort=price_asc&per_page=20', options)
    .then(response => {
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        return response.text();
    })
    .then(data => console.log(data))
    .catch(error => console.error('Error:', error));
JavaScript
const axios = require('axios');

const options = {
    method: 'GET',
    url: 'https://scrappa.co/api/apartmentlist/search?location_id=642592&beds=2&price_max=1500&sort=price_asc&per_page=20',
    headers: {
        x-api-key: 'YOUR_API_KEY_HERE',
    }
};

try {
    const response = await axios(options);
    console.log(response.data);
} catch (error) {
    console.error('Error:', error.message);
}
Ruby
require 'net/http'
require 'uri'

uri = URI.parse("https://scrappa.co/api/apartmentlist/search?location_id=642592&beds=2&price_max=1500&sort=price_asc&per_page=20")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == 'https'

request = Net::HTTP::Get.new(uri.request_uri)
request['x-api-key'] = 'YOUR_API_KEY_HERE'

begin
    response = http.request(request)
    puts response.body
rescue => e
    puts "Error: #{e.message}"
end
Python
import http.client
import json

conn = http.client.HTTPSConnection("scrappa.co")

headers = {
    'x-api-key': 'YOUR_API_KEY_HERE',
}

try:
    conn.request("GET", "/api/apartmentlist/search?location_id=642592&beds=2&price_max=1500&sort=price_asc&per_page=20", headers=headers)
    res = conn.getresponse()
    data = res.read()
    print(data.decode("utf-8"))
except Exception as e:
    print(f"Error: {e}")
finally:
    conn.close()
Python
import requests

headers = {
    'x-api-key': 'YOUR_API_KEY_HERE',
}

try:
    response = requests.get('https://scrappa.co/api/apartmentlist/search?location_id=642592&beds=2&price_max=1500&sort=price_asc&per_page=20', headers=headers)
    response.raise_for_status()
    print(response.text)
except requests.exceptions.RequestException as e:
    print(f"Error: {e}")
Java
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;

public class ApiExample {
    public static void main(String[] args) {
        OkHttpClient client = new OkHttpClient();

        Request request = new Request.Builder()
            .url("https://scrappa.co/api/apartmentlist/search?location_id=642592&beds=2&price_max=1500&sort=price_asc&per_page=20")
        .addHeader("x-api-key", "YOUR_API_KEY_HERE")
            .build();

        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                System.out.println(response.body().string());
            } else {
                System.out.println("Error: " + response.code());
            }
        } catch (IOException e) {
            System.out.println("Error: " + e.getMessage());
        }
    }
}
Go
package main

import (
    "fmt"
    "net/http"
    "io/ioutil"
)

func main() {
    client := &http.Client{}
    req, err := http.NewRequest("GET", "https://scrappa.co/api/apartmentlist/search?location_id=642592&beds=2&price_max=1500&sort=price_asc&per_page=20", nil)
    if err != nil {
        fmt.Println("Error creating request:", err)
        return
    }
    req.Header.Set("x-api-key", "YOUR_API_KEY_HERE")

    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Error making request:", err)
        return
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Error reading response:", err)
        return
    }

    fmt.Println(string(body))
}
Terminal
#!/bin/bash

curl -X GET \
    -H "x-api-key: YOUR_API_KEY_HERE" \
    "https://scrappa.co/api/apartmentlist/search?location_id=642592&beds=2&price_max=1500&sort=price_asc&per_page=20"
C#
using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        using var client = new HttpClient();
        client.DefaultRequestHeaders.Add("x-api-key", "YOUR_API_KEY_HERE");

        try
        {
            var response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, "https://scrappa.co/api/apartmentlist/search?location_id=642592&beds=2&price_max=1500&sort=price_asc&per_page=20"));
            var content = await response.Content.ReadAsStringAsync();
            Console.WriteLine(content);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}
TypeScript
import axios from 'axios';

async function run(): Promise<void> {
    try {
        const response = await axios({
            method: 'GET',
            url: 'https://scrappa.co/api/apartmentlist/search?location_id=642592&beds=2&price_max=1500&sort=price_asc&per_page=20',
            headers: {
        'x-api-key': 'YOUR_API_KEY_HERE',
            },
        });

        console.log(response.data);
    } catch (error) {
        console.error('Error:', error);
    }
}

void run();
RUST
use reqwest::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new();

    let response = client
        .get("https://scrappa.co/api/apartmentlist/search?location_id=642592&beds=2&price_max=1500&sort=price_asc&per_page=20")
        .header("x-api-key", "YOUR_API_KEY_HERE")
        .send()
        .await?;

    println!("{}", response.text().await?);

    Ok(())
}

Response Schema

Example response fields are illustrative; inspect the JSON before integrating.

Example response fields

Scan these fields before integrating.

success total total_units returned pagination applied_filters listings meta

Common listings fields

rental_id slug url name
JSON Response
200 OK
{
    "success": true,
    "total": 357,
    "total_units": 4168,
    "returned": 1,
    "pagination": {
        "page": 1,
        "per_page": 20,
        "total_pages": 18,
        "has_next_page": true
    },
    "applied_filters": {
        "location_id": 642592,
        "beds": [
            2
        ],
        "price_max": 1500,
        "sort": "price_asc"
    },
    "listings": [
        {
            "rental_id": "p191304",
            "slug": "/tx/austin/polaris-on-the-park",
            "url": "https://www.apartmentlist.com/tx/austin/polaris-on-the-park",
            "name": "Polaris on the Park",
            "address": "1720 Woodward Street, Austin, TX 78741",
            "neighborhood": "Parker Lane",
            "geo": {
                "lat": 30.219922,
                "lon": -97.743986
            },
            "phone": "(555) 010-0100",
            "bed_range": [
                2
            ],
            "price_range": {
                "lowest": 1049,
                "highest": 1499,
                "by_bed_count": {
                    "2": {
                        "min": 1049,
                        "max": 1499
                    }
                }
            },
            "units_available": 29,
            "soonest_available": "2026-10-10",
            "floorplans": [
                {
                    "floorplan_id": 8983421,
                    "name": "2 Bedroom",
                    "bed": 2,
                    "bath": 1.5,
                    "sqft": 904,
                    "sqft_max": 904,
                    "price": 1049,
                    "units": [
                        {
                            "unit_id": "p191304-aaea9642-f14a-11e9-a811-1866dab905f4",
                            "name": "1716-111",
                            "price": 1049,
                            "base_price": 1049,
                            "total_price": null,
                            "required_fees": null,
                            "sqft": 904,
                            "available_on": "2026-10-10",
                            "available_now": true,
                            "lease_length": 12,
                            "apply_online_url": "https://example.com/apply"
                        }
                    ]
                }
            ],
            "photos": [
                "https://cdn.apartmentlist.com/image/upload/c_fill,dpr_auto,f_auto,g_center,h_415,q_auto,w_640/4d2d7bc54a662f16cebd8dac28ade93c.jpg"
            ],
            "community_amenities": [
                {
                    "name": "Dogs allowed",
                    "key": "is_dog_friendly",
                    "group": "pets"
                }
            ],
            "unit_amenities": [
                {
                    "name": "Dishwasher",
                    "key": "has_dishwasher",
                    "group": "unit_features"
                }
            ],
            "amenities_text": "On-site laundry, Google fiber, Patio / balcony, Hardwood floors, Dishwasher, Pet friendly + more",
            "has_rent_special": false,
            "rating": 4,
            "review_summary": {
                "title": "An oasis near vibrant Austin hotspots.",
                "text": "Residents like the dog park and the courtyards.",
                "tag": "Pet Paradise"
            },
            "is_featured": false,
            "featured_tag": null,
            "featured_description": null,
            "show_price": true,
            "source_name": "show_me_the_rent",
            "is_fee_transparent": false,
            "occupancy_types": [],
            "updated_at": "2026-10-26T01:27:49.617Z"
        }
    ],
    "meta": {
        "endpoint_family": "search",
        "billable": true,
        "attempts": 2,
        "omitted": 0,
        "id_list_cached": false
    }
}

Errors

Handle these documented responses before retrying or showing customer-facing failures.

422

Unknown Location

The `location_id` is not an Apartment List location (`unknown_location`). Take the id from location-autocomplete. Non-billable.

{
    "meta": {
        "attempts": 1,
        "billable": false,
        "retryable": false,
        "endpoint_family": "search"
    },
    "error": {
        "code": "unknown_location",
        "message": "Unknown location_id. Use an id from /api/apartmentlist/location-autocomplete."
    },
    "success": false
}
422

Validation Error

A query parameter is missing, unknown or unusable. Unknown parameters are rejected, never ignored (`request_rejected` is the same failure raised by the source). Non-billable.

{
    "errors": {
        "sort": [
            "The selected sort is invalid."
        ]
    },
    "message": "The selected sort is invalid."
}
503

Source Unavailable

Apartment List could not be reached in time, answered with an error, or its page layout changed (`upstream_unavailable`, `upstream_blocked`, `deadline_exhausted`, `parser_drift`). Retryable and never billed. Clients are never rate limited.

{
    "meta": {
        "attempts": 6,
        "billable": false,
        "retryable": true,
        "endpoint_family": "search"
    },
    "error": {
        "code": "upstream_unavailable",
        "message": "Apartment List is temporarily unavailable. Please retry."
    },
    "success": false
}

Generate Code with AI

Copy a ready-made prompt with all the endpoint details, parameters, and example responses. Paste it into ChatGPT, Claude, or any AI assistant to instantly generate working code.

Try It Live

Test this endpoint in our interactive playground with real data.