# Geebo Scraper (`crawlerbros/geebo-scraper`) Actor

Scrape Geebo.com free classifieds - jobs, real estate, vehicles, merchandise, rentals, and services. Search by keyword or browse a category/type, filter by price, ZIP radius, and location.

- **URL**: https://apify.com/crawlerbros/geebo-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Jobs, Real estate, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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

## Geebo Scraper

Scrape [Geebo.com](https://geebo.com) — a free US classifieds site covering jobs, real estate,
vehicles, merchandise (for-sale), rentals & roommates, services, and construction/farm equipment.
No login, no API key, no cookies. Works out of the box on the Apify free plan.

### What this actor does

- **Two modes:** keyword `search` inside a category, or `browse` a category/type without a keyword
- **99 category → type combinations** exposed as a single searchable dropdown (7 top-level
  categories × their real subcategories, e.g. `Jobs → Information Technology (IT)`,
  `Vehicles → Motorcycles`, `Real Estate → Apartments`)
- **Location radius search parameters** — optional ZIP code + mile radius, passed through to
  Geebo's own URL scheme (note: Geebo's server-rendered pages have been observed to ignore this
  and return the same nationwide results regardless — use `locationContains` below for reliable
  location filtering instead)
- **Client-side filters** — min/max price (listings with no displayed price are excluded when a
  price filter is active, since they can't be verified to be in range), must-contain keyword,
  location substring
- **Optional deep enrichment** — turn on `fetchFullDetails` to also pull the full description,
  the complete photo gallery, and the ZIP code from each listing's detail page
- Every output field is only included when Geebo actually provided real data — no `null`,
  no placeholder text

### Output per listing

- `title`, `sourceUrl`
- `category`, `categoryLabel`, `type`
- `location`
- `price`, `currency` (when a price is shown) or `contactSellerForPrice: true` (when a for-sale
  listing has no visible price). Not emitted at all for `jobs-online`, `services`, or
  `construction-farm-equipment` — Geebo never shows a price for those categories, so the
  field is omitted entirely rather than implying a seller withheld one
- `companyName` (job listings)
- `description` (listing snippet)
- `imageUrl` (listing thumbnail)
- `isNew` — true if Geebo flagged the listing "NEW!"
- When `fetchFullDetails` is on: `fullDescription`, `images[]`, `zipCode`
- `itemId`, `recordType: "listing"`, `scrapedAt`

### Input

| Field | Type | Console prefill | Description |
|---|---|---|---|
| `mode` | select | `search` | `search` or `browse` |
| `categoryType` | select | `merchandise:` (All types) | Category, optionally narrowed to a type. Required in both modes - no forced default via API, so this must be supplied explicitly on programmatic calls |
| `searchQuery` | string | `furniture` | Keyword (mode=search). No forced default via API - required in `search` mode |
| `zipCode` | string | – | US ZIP code to center a radius search on (see note above — not currently honored server-side by Geebo) |
| `distanceMiles` | integer | `50` | Radius in miles around `zipCode` (same caveat) |
| `minPrice` / `maxPrice` | integer | – | Price range filter (USD) |
| `keyword` | string | – | Extra substring filter on title/description |
| `locationContains` | string | – | Extra substring filter on location |
| `fetchFullDetails` | boolean | `false` | Fetch each listing's detail page for full description/photos/ZIP |
| `maxItems` | integer | `30` | Max records to return (1–500) |

### Example input

```json
{
  "mode": "search",
  "categoryType": "vehicles:10-bicycles-",
  "searchQuery": "mountain bike",
  "zipCode": "90210",
  "distanceMiles": 100,
  "maxItems": 20
}
```

#### Example: browse job listings without a keyword

```json
{
  "mode": "browse",
  "categoryType": "jobs-online:23-information-technology-it-",
  "maxItems": 20
}
```

#### Example: for-sale merchandise with a price range and full detail

```json
{
  "mode": "search",
  "categoryType": "merchandise:7-furniture-",
  "searchQuery": "sofa",
  "minPrice": 50,
  "maxPrice": 300,
  "fetchFullDetails": true,
  "maxItems": 20
}
```

### Use cases

- **Classifieds aggregation** — pull fresh listings across jobs, real estate, vehicles, or merchandise into your own marketplace or search tool
- **Price monitoring** — track pricing trends for a category (e.g. used vehicles, furniture) over time
- **Local market research** — filter by `locationContains` to see what's being listed in a specific city or state
- **Job board syndication** — collect job postings from a specific category to republish or analyze
- **Lead generation** — find sellers or service providers (e.g. skilled trades, home services) offering in a given category

### Data source & reliability

Geebo.com serves fully server-rendered HTML for both its listing pages and detail pages —
no JavaScript rendering, no login wall, no CAPTCHA. The actor uses plain HTTP requests
(`httpx`) routed through Apify's free datacenter (AUTO) proxy, with automatic retries and
session rotation on rate-limit/server errors or connection failures. No paid proxy, login,
or API key is required.

### FAQs

**Do I need a Geebo account or API key?** No — everything scraped is publicly visible.

**Why do some listings not have a `price` field?** Geebo lets sellers list "Contact seller
for price" instead of a number. Those listings get `contactSellerForPrice: true` instead of
a fabricated price.

**Can I browse without a keyword?** Yes — use `mode: "browse"` with a `categoryType` such as
`jobs-online:23-information-technology-it-`.

# Actor input Schema

## `mode` (type: `string`):

`search` runs a keyword search inside the chosen category. `browse` lists a category/type without a keyword.

## `categoryType` (type: `string`):

Pick the classifieds category, optionally narrowed to a specific type/subcategory. Required for both modes.

## `searchQuery` (type: `string`):

Free-text keyword search, e.g. `bicycle`, `nurse`, `2 bedroom apartment`.

## `zipCode` (type: `string`):

US ZIP code, passed through to Geebo's own radius-search URL. Note: Geebo's server-rendered listing pages have been observed to return the same nationwide result set regardless of this parameter, so it is not a reliable way to narrow results today - use `locationContains` instead for real city/state filtering. Leave blank for nationwide results.

## `distanceMiles` (type: `integer`):

Radius around `zipCode` to search within. Ignored if `zipCode` is blank. See the `zipCode` field note - Geebo does not currently appear to honor this filter server-side.

## `minPrice` (type: `integer`):

Drop listings priced below this. Listings with no visible price (contact seller) are excluded whenever a min/max price filter is active, since their price can't be verified to be in range.

## `maxPrice` (type: `integer`):

Drop listings priced above this. Listings with no visible price (contact seller) are excluded whenever a min/max price filter is active, since their price can't be verified to be in range.

## `keyword` (type: `string`):

Extra client-side filter: only keep listings whose title or description contains this text (case-insensitive).

## `locationContains` (type: `string`):

Extra client-side filter: only keep listings whose location text contains this substring, e.g. `CA` or `Chicago`.

## `fetchFullDetails` (type: `boolean`):

When enabled, opens each listing's detail page to add the full description, full photo gallery, and ZIP code (slower, one extra request per listing).

## `maxItems` (type: `integer`):

Hard cap on emitted records.

## Actor input object example

```json
{
  "mode": "search",
  "categoryType": "merchandise:",
  "searchQuery": "furniture",
  "distanceMiles": 50,
  "fetchFullDetails": false,
  "maxItems": 30
}
```

# Actor output Schema

## `listings` (type: `string`):

Dataset containing all scraped Geebo classified listings.

# 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 = {
    "mode": "search",
    "categoryType": "merchandise:",
    "searchQuery": "furniture",
    "distanceMiles": 50,
    "fetchFullDetails": false,
    "maxItems": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/geebo-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 = {
    "mode": "search",
    "categoryType": "merchandise:",
    "searchQuery": "furniture",
    "distanceMiles": 50,
    "fetchFullDetails": False,
    "maxItems": 30,
}

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

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

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

```

## CLI example

```bash
echo '{
  "mode": "search",
  "categoryType": "merchandise:",
  "searchQuery": "furniture",
  "distanceMiles": 50,
  "fetchFullDetails": false,
  "maxItems": 30
}' |
apify call crawlerbros/geebo-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=crawlerbros/geebo-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/pdEFMMTbaeyBha4KI/builds/D3wgivx1kXEJLda0l/openapi.json
