> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hasdata.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Redfin Property Scraper

Track housing prices, scout investment properties, and analyze neighborhood trends without writing code. Returns property URL, address, price, beds, baths, living area, listing status, photos, and key listing metadata.

This scraper job is asynchronous. You'll receive a `jobId`, and can fetch results via polling or webhook delivery.

## Request Cost

Each row of data returned consumes **10 credits** from your balance.

<Tip>Credits are deducted only for successful rows.</Tip>

## Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://api.hasdata.com/scrapers/redfin/jobs' \
    --header 'Content-Type: application/json' \
    --header 'x-api-key: <your-api-key>' \
    --data '{"limit":120,"locations":["33321","33068"],"type":"forSale"}'
  ```

  ```javascript Node.js theme={null}
  const axios = require('axios').default;

  const options = {
    method: 'POST',
    url: 'https://api.hasdata.com/scrapers/redfin/jobs',
    headers: {'Content-Type': 'application/json', 'x-api-key': '<your-api-key>'},
    data: {limit: 120, locations: ['33321', '33068'], type: 'forSale'}
  };

  try {
    const { data } = await axios.request(options);
    console.log(data);
  } catch (error) {
    console.error(error);
  }
  ```

  ```python Python theme={null}
  import requests

  url = "https://api.hasdata.com/scrapers/redfin/jobs"

  payload = {
      "limit": 120,
      "locations": ["33321", "33068"],
      "type": "forSale"
  }
  headers = {
      "Content-Type": "application/json",
      "x-api-key": "<your-api-key>"
  }

  response = requests.post(url, json=payload, headers=headers)

  print(response.json())
  ```

  ```php PHP theme={null}
  <?php

  $payload = [
      "limit" => 120,
      "locations" => ["33321", "33068"],
      "type" => "forSale",
  ];

  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://api.hasdata.com/scrapers/redfin/jobs",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => json_encode($payload),
    CURLOPT_HTTPHEADER => [
      "Content-Type: application/json",
      "x-api-key: <your-api-key>",
    ],
  ]);

  $response = curl_exec($curl);
  curl_close($curl);

  echo $response;
  ```

  ```java Java theme={null}
  OkHttpClient client = new OkHttpClient();

  MediaType mediaType = MediaType.parse("application/json");
  String json = """
    {
      "limit": 120,
      "locations": [
        "33321",
        "33068"
      ],
      "type": "forSale"
    }
  """;
  RequestBody requestBody = RequestBody.create(json, mediaType);

  Request request = new Request.Builder()
    .url("https://api.hasdata.com/scrapers/redfin/jobs")
    .post(requestBody)
    .addHeader("Content-Type", "application/json")
    .addHeader("x-api-key", "<your-api-key>")
    .build();

  Response response = client.newCall(request).execute();
  ```

  ```csharp C# theme={null}
  using System.Net.Http;
  using System.Text;

  var client = new HttpClient();

  var json = """
  {
    "limit": 120,
    "locations": [
      "33321",
      "33068"
    ],
    "type": "forSale"
  }
  """;
  var content = new StringContent(json, Encoding.UTF8, "application/json");

  var request = new HttpRequestMessage(new HttpMethod("POST"), "https://api.hasdata.com/scrapers/redfin/jobs")
  {
      Content = content,
  };
  request.Headers.Add("x-api-key", "<your-api-key>");

  using var response = await client.SendAsync(request);
  response.EnsureSuccessStatusCode();
  var body = await response.Content.ReadAsStringAsync();
  Console.WriteLine(body);
  ```

  ```ruby Ruby theme={null}
  require 'net/http'
  require 'uri'
  require 'json'

  uri = URI("https://api.hasdata.com/scrapers/redfin/jobs")
  payload = {
    "limit" => 120,
    "locations" => ["33321", "33068"],
    "type" => "forSale",
  }

  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  request = Net::HTTP::Post.new(uri)
  request["Content-Type"] = 'application/json'
  request["x-api-key"] = '<your-api-key>'
  request.body = payload.to_json

  response = http.request(request)
  puts response.read_body
  ```

  ```rust Rust theme={null}
  use reqwest::blocking::Client;
  use serde_json::json;

  fn main() -> Result<(), Box<dyn std::error::Error>> {
      let client = Client::new();
      let payload = json!({
          "limit": 120,
          "locations": [
              "33321",
              "33068"
          ],
          "type": "forSale"
      });
      let res = client
          .post("https://api.hasdata.com/scrapers/redfin/jobs")
          .header("Content-Type", "application/json")
          .header("x-api-key", "<your-api-key>")
          .json(&payload)
          .send()?
          .text()?;
      println!("{}", res);
      Ok(())
  }
  ```

  ```go Go theme={null}
  package main

  import (
  	"bytes"
  	"fmt"
  	"io"
  	"net/http"
  )

  func main() {
  	payload := []byte(`{
    "limit": 120,
    "locations": [
      "33321",
      "33068"
    ],
    "type": "forSale"
  }`)

  	req, _ := http.NewRequest("POST", "https://api.hasdata.com/scrapers/redfin/jobs", bytes.NewBuffer(payload))
  	req.Header.Add("Content-Type", "application/json")
  	req.Header.Add("x-api-key", "<your-api-key>")

  	res, _ := http.DefaultClient.Do(req)
  	defer res.Body.Close()

  	responseBody, _ := io.ReadAll(res.Body)
  	fmt.Println(string(responseBody))
  }
  ```
</CodeGroup>

## Job Parameters

<ParamField body="limit" type="number" required>
  Result rows limit
</ParamField>

<ParamField body="locations" type="string[]" required>
  Specify the Zip Codes you want to extract data from.
</ParamField>

<ParamField body="type" type="string" required>
  Type
</ParamField>

## Supported Enrichments

Request any of the fields below via the `enrichments` array in your job payload.

| ID             | Title               | Description                             | Cost per Request |
| -------------- | ------------------- | --------------------------------------- | ---------------- |
| `email`        | Email Address       | Listing agent email address             | 5 credits        |
| `website`      | Website URL         | Listing agent or brokerage website URL  | 5 credits        |
| `phone`        | Phone Number        | Listing agent or brokerage phone number | 5 credits        |
| `linkedinUrl`  | LinkedIn Profile    | Listing agent LinkedIn profile URL      | 5 credits        |
| `facebookUrl`  | Facebook Profile    | Listing agent Facebook profile URL      | 5 credits        |
| `instagramUrl` | Instagram Profile   | Listing agent Instagram profile URL     | 5 credits        |
| `xUrl`         | X (Twitter) Profile | Listing agent X profile URL             | 5 credits        |
| `githubUrl`    | GitHub Profile      | Listing agent GitHub profile URL        | 5 credits        |
| `revenue`      | Revenue             | Brokerage revenue                       | 5 credits        |
| `traffic`      | Website Traffic     | Brokerage website traffic               | 5 credits        |
| `funding`      | Funding Info        | Brokerage funding information           | 5 credits        |
| `founded`      | Founded Year        | Brokerage founded year                  | 5 credits        |

## Getting Results

<Card title="Webhooks" horizontal icon="webhook" href="/scrapers/webhooks">
  Receive real-time updates when your scraper job starts, completes, or collects data.
</Card>

<Card title="Results API" horizontal icon="list" href="/scrapers/getting-results">
  Use the Results API to fetch your data using the `jobId`, with support for polling and pagination.
</Card>

<Card title="Stopping a Job" horizontal icon="circle-stop" href="/scrapers/stopping-job">
  Cancel an active scraper job early if it's no longer needed or you want to save credits.
</Card>
