# BoligPortal Rental Search API Documentation

Scrappa's `GET /api/boligportal/search` returns BoligPortal rental homes in Denmark as structured JSON, 18 homes per page.

## Rentals only

BoligPortal lists homes for rent. It has no sale listings and no bathroom count, so this API has no sale or bathroom parameter. Agency profiles are not available; `listing` returns the landlord facts BoligPortal shows publicly.

## What you get

Each home has `id`, `url`, `title`, `category`, `state`, the address parts and `postal_code`, `rooms`, `size_m2`, `monthly_rent` with `currency` DKK, `monthly_rent_extra_costs`, `deposit`, `prepaid_rent`, `rental_period`, `available_from`, `advertised_date`, the energy label, 14 `features` flags, `images`, `location` coordinates and listing flags. `description` is empty in search results; call `listing` for it. `result_count` is BoligPortal's own match count and `anchor_links` lists city match counts.

## Filters are honoured

BoligPortal rounds rooms (1.5 rooms matches a search for 2), and it can leave a feature flag unknown. Scrappa checks every returned home again against `min_rooms`, `max_rooms`, size, rent, type and each feature flag, and drops homes that do not match. `meta.filtered_out_count` says how many were dropped, so a page can hold fewer than 18 homes while `pagination.has_next` stays true.

## Sort

`order` is DEFAULT (newest first), RENT_ASC, RENT_DESC, SIZE_M2_DESC or SIZE_M2_ASC. BoligPortal puts promoted homes first even when a sort is asked for, so Scrappa sorts the returned page by the requested key (`meta.sorted_within_page`). Paging across pages follows BoligPortal. It does not break ties, so homes with the same rent or size can swap places between pages and one home can show on two adjacent pages.

## Locations

`location` is a city from BoligPortal's own city list. An unknown city returns `422` (`unknown_location`) with suggestions and costs nothing. `district` and `area` narrow inside the city.

## Pagination

`page` is 1-based. A page past the last one returns an empty list with `has_next` false. A page is never labelled with another page's homes.

- **Documentation:** [https://scrappa.co/docs/boligportal-api/boligportal_search](https://scrappa.co/docs/boligportal-api/boligportal_search)
- **API group:** BoligPortal API
- **Endpoint:** `GET https://scrappa.co/api/boligportal/search`

## Authentication

Send your Scrappa API key in the `X-API-KEY` request header. Paid endpoints also support accountless x402 payments when called without an API key.

## Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `location` | string | No | City such as København, Aarhus or Odense (not case sensitive). Unknown cities return 422 with suggestions. |
| `district` | string | No | District inside the city, for example valby or frederiksberg. |
| `area` | string | No | Neighbourhood inside the district. |
| `street` | string | No | Street name, for example Gammel Køge Landevej. |
| `type` | string | No | apartment, house, townhouse or room. Comma-separated. |
| `min_rooms` | number | No | Minimum number of rooms, halves allowed, for example 1.5. Applied exactly: the platform rounds, so results are checked again. |
| `max_rooms` | number | No | Maximum number of rooms, halves allowed. |
| `min_size` | integer | No | Minimum size in square metres. |
| `max_size` | integer | No | Maximum size in square metres. |
| `min_rent` | integer | No | Minimum monthly rent in DKK, without extra costs. |
| `max_rent` | integer | No | Maximum monthly rent in DKK, without extra costs. |
| `min_rental_period` | integer | No | Minimum rental period in months. |
| `available_before` | string | No | Latest move-in date, YYYY-MM-DD. |
| `min_lat` | number | No | South edge of a bounding box. Send all four box values or none. |
| `max_lat` | number | No | North edge of a bounding box. |
| `min_lng` | number | No | West edge of a bounding box. |
| `max_lng` | number | No | East edge of a bounding box. |
| `pet_friendly` | boolean | No | true to require the feature. false or omitted applies no filter. Homes where the feature is unknown are left out. |
| `furnished` | boolean | No | true to require the feature. false or omitted applies no filter. Homes where the feature is unknown are left out. |
| `balcony` | boolean | No | true to require the feature. false or omitted applies no filter. Homes where the feature is unknown are left out. |
| `parking` | boolean | No | true to require the feature. false or omitted applies no filter. Homes where the feature is unknown are left out. |
| `elevator` | boolean | No | true to require the feature. false or omitted applies no filter. Homes where the feature is unknown are left out. |
| `shareable` | boolean | No | true to require the feature. false or omitted applies no filter. Homes where the feature is unknown are left out. |
| `student_only` | boolean | No | true to require the feature. false or omitted applies no filter. Homes where the feature is unknown are left out. |
| `senior_friendly` | boolean | No | true to require the feature. false or omitted applies no filter. Homes where the feature is unknown are left out. |
| `social_housing` | boolean | No | true to require the feature. false or omitted applies no filter. Homes where the feature is unknown are left out. |
| `newbuild` | boolean | No | true to require the feature. false or omitted applies no filter. Homes where the feature is unknown are left out. |
| `electric_charging_station` | boolean | No | true to require the feature. false or omitted applies no filter. Homes where the feature is unknown are left out. |
| `dishwasher` | boolean | No | true to require the feature. false or omitted applies no filter. Homes where the feature is unknown are left out. |
| `washing_machine` | boolean | No | true to require the feature. false or omitted applies no filter. Homes where the feature is unknown are left out. |
| `dryer` | boolean | No | true to require the feature. false or omitted applies no filter. Homes where the feature is unknown are left out. |
| `order` | string | No | DEFAULT (newest first), RENT_ASC, RENT_DESC, SIZE_M2_DESC or SIZE_M2_ASC. |
| `page` | integer | No | Result page, 1-based. 18 homes per page. |

## Example request

```bash
#!/bin/bash

curl -X GET \
    -H "x-api-key: YOUR_API_KEY_HERE" \
    "https://scrappa.co/api/boligportal/search?location=K%C3%B8benhavn&type=apartment&max_rent=12000&min_rooms=2&max_rooms=2&pet_friendly=true&order=RENT_ASC"
```

## Example response

```json
{
    "success": true,
    "result_count": 216,
    "returned": 1,
    "pagination": {
        "page": 1,
        "per_page": 18,
        "pages_count": 12,
        "has_next": true,
        "next_page": 2
    },
    "applied_filters": {
        "location": "k\u00f8benhavn",
        "type": [
            "apartment"
        ],
        "max_rent": 12000,
        "order": "RENT_ASC"
    },
    "listings": [
        {
            "id": 5450948,
            "url": "https://www.boligportal.dk/lejligheder/k%C3%B8benhavn/53m2-2-vaer-id-5450948",
            "title": "Perfekt delevenlig 2 v\u00e6relses Valby lejlighed",
            "category": "rental_apartment",
            "state": "ACTIVE_APPROVED",
            "city": "K\u00f8benhavn",
            "city_area": "Valby",
            "city_level_1": "k\u00f8benhavn",
            "city_level_2": "valby",
            "city_level_3": null,
            "postal_code": "2500",
            "street_name": "Gammel K\u00f8ge Landevej",
            "street_number": "178",
            "floor": 2,
            "rooms": 2,
            "size_m2": 53,
            "monthly_rent": 10000,
            "currency": "DKK",
            "monthly_rent_extra_costs": 500,
            "deposit": 30000,
            "prepaid_rent": 0,
            "rental_period": 0,
            "available_from": null,
            "advertised_date": "2026-10-24T14:53:16.021199+00:00",
            "created": "2024-08-11T16:12:32.761437+00:00",
            "energy_rating": "D",
            "energy_label_valid_to": "2030-11-21",
            "features": {
                "pet_friendly": true,
                "furnished": false,
                "balcony": true,
                "parking": true,
                "elevator": false,
                "shareable": true,
                "student_only": false,
                "senior_friendly": false,
                "electric_charging_station": null,
                "dishwasher": true,
                "washing_machine": null,
                "dryer": null,
                "social_housing": false,
                "newbuild": false
            },
            "images": [
                {
                    "url": "https://image-lambda.boligportal.dk/8a0bcaa57234198fed3464214dad171a",
                    "is_floor_plan": false
                }
            ],
            "location": {
                "lat": 55.645,
                "lng": 12.503
            },
            "is_newbuild": false,
            "social_housing": false,
            "has_video": false,
            "digital_showing": false,
            "open_house": null,
            "is_promoted": false,
            "has_owner": true
        }
    ],
    "anchor_links": [
        {
            "name": "K\u00f8benhavn S",
            "count": 74
        }
    ],
    "meta": {
        "endpoint_family": "search",
        "currency": "DKK",
        "filtered_out_count": 0,
        "sorted_within_page": true,
        "billable": true
    }
}
```

## Errors

| Status | Error | Description |
| --- | --- | --- |
| 422 | Unknown Location | The `location` is not a BoligPortal city (`unknown_location`). BoligPortal would answer an unknown city with zero results, so the request is rejected with up to five suggestions. Non-billable. |
| 422 | Validation Error | A query parameter is missing, unknown or unusable. Unknown parameters are rejected, never ignored. Sale, bathroom and agency filters do not exist. Non-billable. |
| 503 | Upstream Unavailable | BoligPortal could not be reached after retries, blocked the request, returned another page than asked for, or returned a page this API could not read (`upstream_unavailable`, `upstream_blocked`, `offset_mismatch`, `parser_drift`, `transport_unavailable`, `no_exit_available`). Retryable and never billed. Clients are never rate limited. |

## More Scrappa resources

- [API documentation](https://scrappa.co/docs)
- [Full LLM-readable API reference](https://scrappa.co/llms-full.txt)
- [OpenAPI specification](https://scrappa.co/docs/api.json)
- [Pricing](https://scrappa.co/pricing)
