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

Fincaraiz Search API Documentation

GET https://scrappa.co/api/fincaraiz/search?operation_type_id=1&property_type_id=2&maxPrice=400000000&bedrooms=3&rows=10

Scrappa's GET /api/fincaraiz/search returns Colombian property listings for sale (operacion=venta) or for rent (operacion=arriendo) as structured JSON, instead of the HTML you would otherwise have to scrape.

What you get

One request returns a page of listings plus the platform's own match count in total. That count comes from the platform's search index and is the only number on this API that reflects the full result set — the totals on the enrichment endpoints do not, and the pagination fields are derived from this one.

Each listing is returned essentially as the platform publishes it: id, title, description, price (amount and currency), bedrooms, bathrooms, area, address, typeID, facilities, latitude/longitude, created_at, sold, soldDate, and the full nested locations tree. On top of that, images is a flat list of image URLs, image_count and has_images describe them, and active tells you whether the listing is currently live.

Titles are published with double spaces and are returned exactly as written.

Geography

Use locations, not a city name. Colombia uses two unrelated id vocabularies on this platform: search geography is a UUID, while the numbered estate ids used by the location vocabulary do not work here at all. Get the right value from /api/fincaraiz/location-autocomplete?term=medellin, which returns each match together with the exact id and type pair to pass back.

Each location needs both an id and a type, for example locations[0][id]=...&locations[0][type]=CITY. Omitting the type is rejected.

Filters that silently do nothing

This platform accepts a set of parameter names and ignores them completely: you get a normal 200 with a correct-looking result set and an unchanged total. Rather than pass that on, this API rejects them with a 422, along with any name it does not support. So a request that returns 200 has had every filter you asked for applied.

The fair_active flag is separately rejected under any spelling: it is an internal allowlist switch that reduces a corpus of more than 180,000 listings to roughly 130.

Ranges and units

Prices are whole Colombian pesos and are large — a typical apartment is in the hundreds of millions. Supply them as plain integers. Area is in square metres. Filters intersect: a minimum and maximum price narrow the result together rather than one replacing the other.

What this API does not cover

This is read-only listing data. There is no account access, no messaging or contact-form submission, and no listing creation. The platform publishes no reviews or ratings and no price history, so neither appears here. Sold and expired listings are not reachable through a filter: the platform has no lifecycle filter, so active, sold, and soldDate are per-listing flags you read rather than filter on.

Fincaraiz Search API Documentation 1 credit/request

Endpoint

Request preview
GET
https://scrappa.co/api/fincaraiz/search?operation_type_id=1&property_type_id=2&maxPrice=400000000&bedrooms=3&rows=10
Auth header
x-api-key
Cost
1 credit/request
Response preview
200 OK
{
    "success": true,
    "total": 83191,
    "page": 1,
    "rows": 10,
    "returned": 10,
    "total_pages": 8320,
    "applied_filters": {
        "operation_type_id": 1,
        "property_type_id": [
            2
        ],
        "maxPrice": 400000000,
        "bedrooms": [
...

Parameters

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

Runnable path

This endpoint has no required query parameters.

16 optional filters available.

operation_type_id integer Optional

1 for sale (venta, the default) or 2 for rent (arriendo).

Example value 1
property_type_id integer Optional

One or more of 1 house, 2 apartment, 3 lot, 4 commercial premises. Repeatable, or comma-separated.

Example value 2
minPrice integer Optional

Minimum price in Colombian pesos, as a whole number (e.g. 200000000).

Example value 10
maxPrice integer Optional

Maximum price in Colombian pesos.

Example value 400000000
m2Min integer Optional

Minimum area in square metres.

Example value 10
m2Max integer Optional

Maximum area in square metres.

Example value 10
bedrooms integer Optional

Minimum number of bedrooms (a count, not an id). Repeatable.

Example value 3
bathrooms integer Optional

Minimum number of bathrooms. Repeatable.

Example value 10
rooms integer Optional

Minimum number of rooms. Repeatable.

Example value 10
stratum integer Optional

Neighbourhood wealth bracket, 1-6. Repeatable.

Example value 10
locations string Optional

One or more location objects, each with an id and a type, both required. Ids come from location-autocomplete. Format: locations[0][id]=UUID&locations[0][type]=CITY.

Example value example
order integer Optional

Result ordering code. This sorts results and never changes the total.

Example value 10
owner_id integer Optional

Restrict results to one agency's inventory.

Example value 1234567890
privateOwner boolean Optional

Restrict results to private (non-agency) sellers.

Example value true
rows integer Optional

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

Example value 10
page integer Optional

Result page, 1-based. A page past the end returns a valid but empty page, not an error.

Example value 1

Request Examples

PHP
<?php

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => "https://scrappa.co/api/fincaraiz/search?operation_type_id=1&property_type_id=2&maxPrice=400000000&bedrooms=3&rows=10",
    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/fincaraiz/search?operation_type_id=1&property_type_id=2&maxPrice=400000000&bedrooms=3&rows=10');

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/fincaraiz/search?operation_type_id=1&property_type_id=2&maxPrice=400000000&bedrooms=3&rows=10', 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/fincaraiz/search?operation_type_id=1&property_type_id=2&maxPrice=400000000&bedrooms=3&rows=10',
    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/fincaraiz/search?operation_type_id=1&property_type_id=2&maxPrice=400000000&bedrooms=3&rows=10")
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/fincaraiz/search?operation_type_id=1&property_type_id=2&maxPrice=400000000&bedrooms=3&rows=10", 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/fincaraiz/search?operation_type_id=1&property_type_id=2&maxPrice=400000000&bedrooms=3&rows=10', 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/fincaraiz/search?operation_type_id=1&property_type_id=2&maxPrice=400000000&bedrooms=3&rows=10")
        .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/fincaraiz/search?operation_type_id=1&property_type_id=2&maxPrice=400000000&bedrooms=3&rows=10", 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/fincaraiz/search?operation_type_id=1&property_type_id=2&maxPrice=400000000&bedrooms=3&rows=10"
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/fincaraiz/search?operation_type_id=1&property_type_id=2&maxPrice=400000000&bedrooms=3&rows=10"));
            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/fincaraiz/search?operation_type_id=1&property_type_id=2&maxPrice=400000000&bedrooms=3&rows=10',
            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/fincaraiz/search?operation_type_id=1&property_type_id=2&maxPrice=400000000&bedrooms=3&rows=10")
        .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 page rows returned total_pages applied_filters property_types +2 more

Common listings fields

id title price bedrooms
JSON Response
200 OK
{
    "success": true,
    "total": 83191,
    "page": 1,
    "rows": 10,
    "returned": 10,
    "total_pages": 8320,
    "applied_filters": {
        "operation_type_id": 1,
        "property_type_id": [
            2
        ],
        "maxPrice": 400000000,
        "bedrooms": [
            3
        ]
    },
    "property_types": {
        "1": "casa",
        "2": "apartamento",
        "3": "lote",
        "4": "local"
    },
    "listings": [
        {
            "id": 191347339,
            "title": "Apartamento en  Venta en Manga, Cartagena",
            "price": {
                "amount": 880000000,
                "currency": "COP"
            },
            "bedrooms": 3,
            "bathrooms": 2,
            "area": 120,
            "typeID": 2,
            "active": true,
            "sold": false,
            "soldDate": null,
            "image_count": 12,
            "has_images": true,
            "images": [
                "https://cdn4.fincaraiz.com.co/repo/img/example.jpg"
            ],
            "latitude": 10.4236,
            "longitude": -75.5478
        }
    ],
    "meta": {
        "billable": true,
        "endpoint_family": "search",
        "attempts": 1
    }
}

Errors

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

422

Unsupported Filter

A filter name this API does not support, or one the platform accepts and silently ignores, was supplied (`unknown_filter`, `blocked_filter`). Non-billable.

{
    "meta": {
        "billable": false,
        "retryable": false,
        "endpoint_family": "search"
    },
    "error": {
        "code": "unknown_filter",
        "message": "price_min is not a supported filter. Unknown filters are ignored by the platform, so they are rejected instead of silently dropping the filter."
    },
    "success": false
}
422

Validation Error

A query parameter failed validation. Non-billable.

{
    "errors": {
        "operation_type_id": [
            "The operation type field is invalid."
        ]
    },
    "message": "The operation type field is invalid."
}
503

Upstream Unavailable

The upstream request failed or could not be parsed after retries. Retryable and never billed. Clients are never rate limited.

{
    "meta": {
        "attempts": 4,
        "billable": false,
        "retryable": true,
        "last_status": 503,
        "endpoint_family": "search"
    },
    "error": {
        "code": "upstream_unavailable",
        "message": "Fincaraiz is temporarily unavailable. Please retry."
    },
    "success": false
}
503

Unreadable Response

Fincaraiz answered 200 with a body this endpoint cannot read (`parser_drift`). Nothing is charged for it; an empty or reshaped upstream payload is reported rather than published as an empty result. Retryable.

{
    "meta": {
        "billable": false,
        "retryable": true,
        "endpoint_family": "search"
    },
    "error": {
        "code": "parser_drift",
        "message": "Fincaraiz returned an unreadable response. 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.

Related Endpoints

Fincaraiz API FAQ

Does Fincaraiz offer an official API?

No. Fincaraiz publishes no developer API. Scrappa provides a documented read-only API over its public listing surfaces and returns normalized JSON with API key authentication.

Why does my filter get rejected when the website accepts it?

Several parameter names the platform accepts have no effect: the response is a normal 200 with an unchanged total, so the filter would silently do nothing. Those names, plus fair_active, are rejected with a 422 instead. Any request that returns 200 has had all of its filters applied.

Are empty results charged?

A 200 response with zero listings is a valid answer and is billed. Failures — rejected filters, validation errors, and upstream outages — never consume credits.

Can I search by city name?

Not directly. Pass ids and types from the location-autocomplete endpoint. The numbered estate ids from the location vocabulary are a different set and return no results in search.

Try It Live

Test this endpoint in our interactive playground with real data.