# Fincaraiz Colombia Property Scraper (`barefoot_grade/fincaraiz-co-scraper`) Actor

Property listings search across Fincaraiz, a leading Colombian real-estate portal. Structured records: price, area, rooms, address, images and listing URLs. Part of a multi-country real-estate scraper fleet.

- **URL**: https://apify.com/barefoot\_grade/fincaraiz-co-scraper.md
- **Developed by:** [Philip Kirkbride](https://apify.com/barefoot_grade) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Fincaraiz CO Property Scraper (Colombia, Next.js native extraction)

Property listings from [fincaraiz.com.co](https://www.fincaraiz.com.co) (Colombia):
apartment/house searches for sale (venta) and rental (arriendo), scoped by city,
normalized to the Navent-family record shape (price COP, area m², bedrooms,
bathrooms, address/location, listing URL, images, posted date).

**Next.js native extraction** — the search page is Next.js SSR, and the complete
result set rides a single `__NEXT_DATA__` JSON blob embedded in the page. The
Actor parses that structured state directly: no browser, no HTML scraping of
cards, no OAuth, no challenge solving. A JSON-LD fallback lane covers pages
where the state is incomplete.

### Access lane (verified 2026-09-04)

`www.fincaraiz.com.co` **403s plain datacenter egress** — IP reputation, not
bot protection. The identical request over **Colombian residential egress**
returns the full page (200, ~900 KB). This is exactly the rot that keeps the
incumbent mid-tier actor at a ~65% success rate while its README claims "no bot
protection requiring proxy": there is no challenge to solve, but the site
rejects datacenter IPs, so a proxy-less datacenter lane fails. This Actor makes
the residential requirement explicit and verified:

1. **External residential proxy** (default for portability): pass `proxyUrl`
   (optionally `proxyUsername`/`proxyPassword`). For DataImpulse, a username
   without a country suffix automatically gains `__cr.co` (Colombian exits).
2. **Apify platform proxy**: with no proxy input the Actor requests the
   RESIDENTIAL proxy group pinned to CO.
3. A 403 fails fast with a clear error naming the lane requirement — never a
   silent partial dataset.

### Input

| Field | Default | Notes |
| --- | --- | --- |
| `operation` | `venta` | `venta` (sale) or `arriendo` (rental). Rent grammar is `/arriendo/apartamentos`. |
| `propertyType` | `apartamento` | `apartamento` or `casa`. |
| `location` | *(empty)* | Optional city or city/department slug — `bogota`, `medellin/antioquia`. Free text is slugified (accents fold). |
| `maxPages` | `1` | 1–5 pages; 21 postings per page. |
| `maxResults` | `50` | Hard stop, 1–200. |
| `requestDelaySecs` | `1.0` | Delay between page fetches (0.5–10). |
| `proxyUrl` | *(empty)* | CO-residential proxy (see above). |

### Output

One record per listing (validated against the Actor's dataset schema):

`id`, `listingKey` (`fincaraiz.com.co:<id>`), `url`, `name`, `price`,
`currency` (COP / USD), `priceUsd` (site-computed), `propertyType`, `areaM2`
(built → terrain → m² fallback chain), `rooms`, `bedrooms`, `bathrooms`,
`parkings`, `address`, `location`, `city`, `region`, `latitude`, `longitude`,
`operation`, `publisher`, `postedAt`, `images[]`, `imageUrl`, `source`,
`country`, `scrapedAt`.

### Usage examples

```json
{ "operation": "venta", "propertyType": "apartamento", "maxResults": 21 }
```

```json
{
  "operation": "arriendo",
  "propertyType": "casa",
  "location": "medellin/antioquia",
  "maxPages": 2,
  "proxyUrl": "http://user:pass@gw.dataimpulse.com:823"
}
```

### Cost

One page ≈ 900 KB over a residential lane ≈ **$0.001/page** at DataImpulse
rates (~$1/GB) — a default single-page run of 21 listings lands around a
tenth of a cent. Five pages / 105 listings ≈ $0.005.

### Notes

- Hidden addresses arrive as the literal `[PLACEHOLDER]` string in the
  payload; they are normalized to `null` (with the neighbourhood kept).
- `rooms` mirrors `bedrooms`: the platform's own `rooms` field is usually 0.
- Legacy URL forms (`/apartamentos-en-venta/`) silently redirect to the
  canonical grammar; the Actor only emits canonical URLs and refuses
  off-canonical redirects (an unknown location slug would otherwise silently
  un-scope the search).
- Tests run offline against fixtures captured live 2026-09-04:
  `python3 -m unittest discover tests` (or pytest) from this directory.

# Actor input Schema

## `operation` (type: `string`):

Listing operation to search: sale (venta) or rental (arriendo). The rent URL grammar is /arriendo/apartamentos — NOT /apartamentos-en-arriendo (the legacy form redirects).

## `propertyType` (type: `string`):

Property type to search: apartments (apartamentos) or houses (casas).

## `location` (type: `string`):

Optional location scope as city or city/department slugs, e.g. "bogota", "bogota/bogota-dc", "medellin/antioquia", "cartagena/bolivar". Free text is slugified ("Bogotá" -> "bogota", "Cartagena de Indias / Bolívar" -> "cartagena-de-indias/bolivar"). Empty searches the whole country.

## `maxPages` (type: `integer`):

Search-result pages to fetch (21 postings per page).

## `maxResults` (type: `integer`):

Stop after this many listings.

## `requestDelaySecs` (type: `number`):

Minimum 0.5 seconds.

## `proxyUrl` (type: `string`):

Colombian residential proxy for the www.fincaraiz.com.co lane (the site 403s plain datacenter egress). Either a full URL with embedded credentials (http://user:pass@gw.dataimpulse.com:823) or bare host:port together with proxyUsername/proxyPassword. A DataImpulse username without a country suffix automatically gains \_\_cr.co (Colombian exits). Empty = fall back to the Apify RESIDENTIAL proxy pinned to CO.

## `proxyUsername` (type: `string`):

Username for proxyUrl when the URL does not embed credentials.

## `proxyPassword` (type: `string`):

Password for proxyUrl when the URL does not embed credentials.

## Actor input object example

```json
{
  "operation": "venta",
  "propertyType": "apartamento",
  "location": "",
  "maxPages": 1,
  "maxResults": 50,
  "requestDelaySecs": 1
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "proxyPassword": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("barefoot_grade/fincaraiz-co-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "proxyPassword": "" }

# Run the Actor and wait for it to finish
run = client.actor("barefoot_grade/fincaraiz-co-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "proxyPassword": ""
}' |
apify call barefoot_grade/fincaraiz-co-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,barefoot_grade/fincaraiz-co-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/SFk2Ri3SahQhQG0uW/builds/0BJOCjdWwgUse4T9V/openapi.json
