Skip to content
Scrappa Get API key
Kyero API 1 credit/request

Kyero Property Search API Documentation

GET https://scrappa.co/api/kyero/search?location_id=31673&location_slug=marbella&operation=sale&min_beds=3&max_price=500000&sort=price_asc

Scrappa's GET /api/kyero/search returns Kyero property listings for sale or rent in Spain, Portugal, Italy and France as structured JSON. Get location_id and location_slug from the autocomplete endpoint.

What you get

One request returns one page of up to 20 listings. Each listing has id, name, price, price_formatted, reference_no, bedrooms, bathrooms, built_m2, plot_m2, property_type, short_description, images, feature_keys, badges, video and virtual tour links, the listing agent, and the path that the property endpoint takes. The response also has location with its parent places, pagination, available_filters and alternate_searches (nearby and parent places with their ids).

Filters are honoured

Kyero silently ignores filter values that are not in its own lists. This API rejects such values with a 422 (unsupported_filter_value) before any lookup, and the rejection is not billed. Allowed values: prices from available_filters.price (sale and rent have different lists), rooms 1-10, built area 50, 100, 150 or 200 m2. Every returned listing is also checked against the filters you sent. A listing that breaks a filter is removed and never returned. applied_filters shows what was applied.

Pagination

page runs from 1 to 50 with 20 listings per page, so at most 1,000 listings per search are reachable. pagination.count is the full match count and pagination.reachable is the part you can page through. Narrow the search with filters or a smaller location to reach the rest. A page above 50 returns a non-billable 422. The response never returns one page's data under another page number.

Property types

property_type accepts any, apartments or villas. Town houses and country houses are not available yet.

Coordinates and fees

Kyero does not publish the exact position of a listing. The property endpoint returns the town centre and says so in coordinates_precision. Kyero publishes no fee fields and no price history.

Kyero Property Search API Documentation 1 credit/request

Endpoint

Request preview
GET
https://scrappa.co/api/kyero/search?location_id=31673&location_slug=marbella&operation=sale&min_beds=3&max_price=500000&sort=price_asc
Auth header
x-api-key
Cost
1 credit/request
location_id = 31673 location_slug = marbella
Response preview
200 OK
{
    "success": true,
    "location": {
        "id": 31673,
        "name": "Marbella",
        "slug": "marbella",
        "type": "City",
        "name_with_country": "Marbella, Spain",
        "nation_id": 55529,
        "country": "es",
        "latitude": 36.50978,
        "longitude": -4.88525,
        "hierarchy": [
            {
...

Parameters

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

Runnable path

2 required parameters needed before sending a request.

15 optional filters available.

location_id integer Required

Location id from the autocomplete endpoint.

Example value 31673
location_slug string Required

Location slug from the autocomplete endpoint.

Example value marbella
operation string Optional

sale (default) or rent.

Example value sale
property_type string Optional

any (default), apartments or villas.

Example value example
min_price integer Optional

A step from available_filters.price. Sale: 50000 to 20000000. Rent per month: 250 to 8000.

Example value 10
max_price integer Optional

A step from available_filters.price.

Example value 500000
min_beds integer Optional

1 to 10.

Example value 3
max_beds integer Optional

1 to 10.

Example value 10
min_baths integer Optional

1 to 10.

Example value 10
max_baths integer Optional

1 to 10.

Example value 10
min_build_size integer Optional

In m2: 50, 100, 150 or 200.

Example value 10
max_build_size integer Optional

In m2: 50, 100, 150 or 200.

Example value 10
features string Optional

Comma-separated, all required: pool, garage, terrace, garden, parking, disabled_access, lift, near_beach, near_shops, near_golf, near_transport.

Example value example
new_build boolean Optional

true to return new builds only.

Example value true
resale_only boolean Optional

true to return resale properties only. Cannot be combined with new_build.

Example value true
sort string Optional

price_asc, price_desc or newest. Without it Kyero uses its default order.

Example value price_asc
page integer Optional

Result page, 1 to 50.

Example value 1

Request Examples

PHP
<?php

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => "https://scrappa.co/api/kyero/search?location_id=31673&location_slug=marbella&operation=sale&min_beds=3&max_price=500000&sort=price_asc",
    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/kyero/search?location_id=31673&location_slug=marbella&operation=sale&min_beds=3&max_price=500000&sort=price_asc');

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/kyero/search?location_id=31673&location_slug=marbella&operation=sale&min_beds=3&max_price=500000&sort=price_asc', 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/kyero/search?location_id=31673&location_slug=marbella&operation=sale&min_beds=3&max_price=500000&sort=price_asc',
    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/kyero/search?location_id=31673&location_slug=marbella&operation=sale&min_beds=3&max_price=500000&sort=price_asc")
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/kyero/search?location_id=31673&location_slug=marbella&operation=sale&min_beds=3&max_price=500000&sort=price_asc", 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/kyero/search?location_id=31673&location_slug=marbella&operation=sale&min_beds=3&max_price=500000&sort=price_asc', 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/kyero/search?location_id=31673&location_slug=marbella&operation=sale&min_beds=3&max_price=500000&sort=price_asc")
        .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/kyero/search?location_id=31673&location_slug=marbella&operation=sale&min_beds=3&max_price=500000&sort=price_asc", 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/kyero/search?location_id=31673&location_slug=marbella&operation=sale&min_beds=3&max_price=500000&sort=price_asc"
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/kyero/search?location_id=31673&location_slug=marbella&operation=sale&min_beds=3&max_price=500000&sort=price_asc"));
            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/kyero/search?location_id=31673&location_slug=marbella&operation=sale&min_beds=3&max_price=500000&sort=price_asc',
            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/kyero/search?location_id=31673&location_slug=marbella&operation=sale&min_beds=3&max_price=500000&sort=price_asc")
        .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 location operation applied_filters listings pagination available_filters alternate_searches +2 more

Common listings fields

id name price price_formatted
JSON Response
200 OK
{
    "success": true,
    "location": {
        "id": 31673,
        "name": "Marbella",
        "slug": "marbella",
        "type": "City",
        "name_with_country": "Marbella, Spain",
        "nation_id": 55529,
        "country": "es",
        "latitude": 36.50978,
        "longitude": -4.88525,
        "hierarchy": [
            {
                "id": 29,
                "name": "Malaga",
                "slug": "malaga",
                "type": "Province"
            }
        ]
    },
    "operation": "sale",
    "applied_filters": {
        "operation": "sale",
        "property_type": "any",
        "sort": "price_asc",
        "min_beds": 3,
        "max_price": 500000
    },
    "listings": [
        {
            "id": 21361013,
            "name": "Apartment in Marbella, Malaga",
            "price": 350000,
            "price_formatted": "\u20ac 350,000",
            "payment_scheme": "for_sale",
            "reference_no": "EI-AC2137",
            "location_id": 31673,
            "property_type": {
                "id": 1,
                "key": "apartment",
                "group_id": 1
            },
            "bedrooms": 3,
            "bathrooms": 2,
            "built_m2": 100,
            "plot_m2": 0,
            "short_description": "Discover a collection of 34 extraordinary apartments and penthouses...",
            "images": [
                "https://img.kyero.com/crop/960x720/properties/21361/21361013/428410368.jpg"
            ],
            "images_count": 31,
            "feature_keys": [
                "garage",
                "lift",
                "terrace",
                "pool",
                "new_build"
            ],
            "badges": [
                "video_tour",
                "remote_viewing"
            ],
            "primary_badge": "new_build",
            "featured": false,
            "virtual_tour_url": null,
            "video_url": "https://vimeo.com/1025703918",
            "remote_viewing_enabled": true,
            "agent": {
                "id": 14222,
                "name": "Example Agency",
                "logo_url": "https://img.kyero.com/fit/125x125/agents/logos/14/14222.jpg",
                "type": "2",
                "prime": true,
                "path": "/en/spain/estate-agents/profile/example-agency-a14222",
                "url": "https://www.kyero.com/en/spain/estate-agents/profile/example-agency-a14222"
            },
            "path": "/en/property/21361013-apartment-for-sale-marbella",
            "url": "https://www.kyero.com/en/property/21361013-apartment-for-sale-marbella"
        }
    ],
    "pagination": {
        "page": 1,
        "pages": 8,
        "per_page": 20,
        "count": 143,
        "reachable": 143,
        "max_pages": 50,
        "has_next": true
    },
    "available_filters": {
        "price": [
            50000,
            75000,
            100000
        ],
        "beds": [
            1,
            2,
            3
        ],
        "baths": [
            1,
            2,
            3
        ],
        "build_size": [
            50,
            100,
            150,
            200
        ],
        "features": [
            "pool",
            "garage"
        ],
        "location_features": [
            "near_beach"
        ],
        "multimedia": [
            "remote_viewing",
            "video",
            "virtual_tour"
        ]
    },
    "alternate_searches": {
        "locations_nearby": [
            {
                "label": "Estepona",
                "location_id": 31466,
                "location_slug": "estepona",
                "path": "/en/estepona-property-for-sale-0l31466"
            }
        ]
    },
    "title": "Properties for sale in Marbella",
    "meta": {
        "billable": true,
        "attempts": 1,
        "last_status": 200,
        "endpoint_family": "search",
        "dropped_by_guard": 0
    }
}

Errors

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

422

Unsupported Filter Value or Page

A price, room or size value that Kyero does not offer, an unusable parameter, or a page above 50 (`unsupported_filter_value`, `invalid_parameter`, `page_out_of_range`). Kyero ignores unknown values, so they are rejected before any lookup. Non-billable.

{
    "meta": {
        "billable": false,
        "retryable": false,
        "endpoint_family": "search"
    },
    "error": {
        "code": "unsupported_filter_value",
        "message": "max_build_size must be one of: 50, 100, 150, 200. Kyero ignores other values, so they are rejected."
    },
    "success": false
}
422

Validation Error

A query parameter failed validation, or a path, id or slug is unusable (`invalid_parameter`). Non-billable.

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

Upstream Unavailable

Kyero could not be reached after retries, answered a different page than requested, did not apply the filters, or answered with a body this API cannot read (`upstream_unavailable`, `upstream_blocked`, `pagination_mismatch`, `filter_not_honoured`, `parser_drift`). Retryable and never billed. Clients are never rate limited.

{
    "meta": {
        "attempts": 3,
        "billable": false,
        "retryable": true,
        "last_status": 302,
        "endpoint_family": "search"
    },
    "error": {
        "code": "upstream_blocked",
        "message": "Kyero rejected the request from our egress pool. 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.