Scrappa's GET /api/qasa/search returns Qasa rental homes in Sweden (market=sweden, the default), Finland (finland) or Norway (norway) as structured JSON.
Rentals only
Qasa lists homes for rent. It has no sale listings, so this API has no sale parameter.
What you get
One request returns one page of homes and Qasa's own match count in total. Each home has id, url, title, description, rent, monthly_cost, tenant_base_fee, currency, rooms, bedrooms, size, home_type, tenant rule flags, rental dates and length, landlord badges, location with coordinates and all images. Call the listing endpoint for amenities, fees, nearby transport and the landlord.
Filters are honoured
Qasa applies every filter itself, so total and the paging always describe the real result set. Unknown parameters are rejected with 422 instead of being ignored. applied_filters echoes what was sent.
Rent, not total cost
min_rent and max_rent filter the monthly rent. monthly_cost is the rent plus the tenant fee, so a home can show a monthly_cost slightly above max_rent. This is correct.
Areas
area takes a name or identifier from /api/qasa/location-autocomplete. An area that does not exist returns 422 (unknown_area) with suggestions, because Qasa would otherwise ignore it and return the whole country. market is taken from the area when you omit it. Qasa decides which homes belong to an area, so a city search can include homes in neighbouring localities.
Pagination
page is 1-based and limit is 1-100. A page past the last one returns an empty list with the correct total. It never returns another page's homes. A page far beyond the end, where Qasa cannot report a real total, returns 422 (page_out_of_range). Deep pages are slower.
Data quality
Values pass through as landlords entered them, so a few homes show unrealistic rents or sizes.
Run this endpoint
Endpoint
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.
24 optional filters available.
string
Optional
sweden (default), finland or norway. Sets the currency: SEK, EUR or NOK.
sweden
string
Optional
Area name or identifier from location-autocomplete, for example Göteborg or se/göteborg.
Göteborg
integer
Optional
Minimum monthly rent as a whole number in the market currency. Applies to the rent, not to rent plus tenant fee.
5000
integer
Optional
Maximum monthly rent as a whole number in the market currency. Applies to the rent, not to rent plus tenant fee.
12000
number
Optional
Minimum room count, for example 1.5.
10
number
Optional
Maximum room count.
10
integer
Optional
Minimum size in square metres.
10
integer
Optional
Maximum size in square metres.
10
integer
Optional
Number of people who will live in the home, 1-20.
10
integer
Optional
Minimum rental length in months.
10
string
Optional
One or more of apartment, terrace_house, cottage, dorm, house, other. Comma-separated.
example
boolean
Optional
true for furnished homes, false for unfurnished.
true
boolean
Optional
true for homes that allow pets, false for homes that do not.
true
boolean
Optional
true for homes that allow smoking, false for homes that do not.
true
boolean
Optional
true or false.
true
boolean
Optional
true for first-hand contracts, false for second-hand.
true
boolean
Optional
true or false.
true
boolean
Optional
true or false.
true
boolean
Optional
true or false.
true
string
Optional
published_or_bumped_at (default), rent, monthly_cost, start_date, end_date, room_count, square_meters, sorting_score or thirty_day_view_count.
relevance
string
Optional
desc (default) or asc.
example
integer
Optional
Homes per page, 1-100 (default 20).
10
integer
Optional
Result page, 1-based.
1
Request Examples
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://scrappa.co/api/qasa/search?market=sweden&area=G%C3%B6teborg&min_rent=5000&max_rent=12000&limit=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
use Illuminate\Support\Facades\Http;
$response = Http::timeout(30)
->withHeaders(['x-api-key' => 'YOUR_API_KEY_HERE'])
->get('https://scrappa.co/api/qasa/search?market=sweden&area=G%C3%B6teborg&min_rent=5000&max_rent=12000&limit=10');
if ($response->successful()) {
echo $response->body();
} else {
echo "Error: " . $response->status();
}
const options = {
method: 'GET',
headers: {
'x-api-key': 'YOUR_API_KEY_HERE'
}
};
fetch('https://scrappa.co/api/qasa/search?market=sweden&area=G%C3%B6teborg&min_rent=5000&max_rent=12000&limit=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));
const axios = require('axios');
const options = {
method: 'GET',
url: 'https://scrappa.co/api/qasa/search?market=sweden&area=G%C3%B6teborg&min_rent=5000&max_rent=12000&limit=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);
}
require 'net/http'
require 'uri'
uri = URI.parse("https://scrappa.co/api/qasa/search?market=sweden&area=G%C3%B6teborg&min_rent=5000&max_rent=12000&limit=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
import http.client
import json
conn = http.client.HTTPSConnection("scrappa.co")
headers = {
'x-api-key': 'YOUR_API_KEY_HERE',
}
try:
conn.request("GET", "/api/qasa/search?market=sweden&area=G%C3%B6teborg&min_rent=5000&max_rent=12000&limit=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()
import requests
headers = {
'x-api-key': 'YOUR_API_KEY_HERE',
}
try:
response = requests.get('https://scrappa.co/api/qasa/search?market=sweden&area=G%C3%B6teborg&min_rent=5000&max_rent=12000&limit=10', headers=headers)
response.raise_for_status()
print(response.text)
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
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/qasa/search?market=sweden&area=G%C3%B6teborg&min_rent=5000&max_rent=12000&limit=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());
}
}
}
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://scrappa.co/api/qasa/search?market=sweden&area=G%C3%B6teborg&min_rent=5000&max_rent=12000&limit=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))
}
#!/bin/bash
curl -X GET \
-H "x-api-key: YOUR_API_KEY_HERE" \
"https://scrappa.co/api/qasa/search?market=sweden&area=G%C3%B6teborg&min_rent=5000&max_rent=12000&limit=10"
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/qasa/search?market=sweden&area=G%C3%B6teborg&min_rent=5000&max_rent=12000&limit=10"));
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(content);
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
import axios from 'axios';
async function run(): Promise<void> {
try {
const response = await axios({
method: 'GET',
url: 'https://scrappa.co/api/qasa/search?market=sweden&area=G%C3%B6teborg&min_rent=5000&max_rent=12000&limit=10',
headers: {
'x-api-key': 'YOUR_API_KEY_HERE',
},
});
console.log(response.data);
} catch (error) {
console.error('Error:', error);
}
}
void run();
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/qasa/search?market=sweden&area=G%C3%B6teborg&min_rent=5000&max_rent=12000&limit=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
market
currency
total
returned
pagination
applied_filters
listings
+1 more
Common listings fields
id
url
title
description
{
"success": true,
"market": "sweden",
"currency": "SEK",
"total": 612,
"returned": 1,
"pagination": {
"page": 1,
"limit": 10,
"pages_count": 62,
"has_next_page": true,
"has_previous_page": false
},
"applied_filters": {
"area": "se/g\u00f6teborg",
"min_rent": 5000,
"max_rent": 12000,
"market": "sweden",
"sort": "published_or_bumped_at",
"direction": "desc"
},
"listings": [
{
"id": "1492340",
"url": "https://qasa.com/se/en/home/1492340",
"title": "Two-room apartment in Majorna",
"description": "Bright apartment close to the tram.",
"market": "sweden",
"currency": "SEK",
"rent": 11200,
"monthly_cost": 11866,
"tenant_base_fee": 666,
"rooms": 2,
"bedrooms": 1,
"size": 48,
"home_type": "apartment",
"furnished": true,
"shared": false,
"first_hand": false,
"student_home": false,
"senior_home": false,
"corporate_home": false,
"pets_allowed": false,
"smoking_allowed": false,
"wheelchair_accessible": false,
"instant_sign": false,
"household_size": 2,
"block_listing": false,
"rental_length_seconds": 15778800,
"rental_length_months": 6,
"start_date": "2026-12-01T00:00:00Z",
"end_date": "2027-05-31T00:00:00Z",
"published_at": "2026-10-25T09:12:00Z",
"last_bumped_at": null,
"published_or_bumped_at": "2026-10-25T09:12:00Z",
"sorting_score": 0.82,
"platform": "blocket",
"display_street_number": true,
"landlord_badges": [],
"location": {
"id": "2210451",
"locality": "G\u00f6teborg",
"country_code": "SE",
"street": "Karl Johansgatan",
"street_number": "12",
"latitude": 57.6948,
"longitude": 11.9189
},
"images": [
{
"id": "22202803",
"url": "https://example.com/home.jpg",
"type": "home_picture",
"order": 1,
"primary": null
}
]
}
],
"meta": {
"endpoint_family": "search",
"billable": true,
"attempts": 1
}
}
Errors
Handle these documented responses before retrying or showing customer-facing failures.
Page Out of Range
The `page` lies so far past the last page that Qasa reports no total (`page_out_of_range`). A page just past the end returns an empty list with the real total instead. Non-billable.
{
"meta": {
"attempts": 1,
"billable": false,
"retryable": false,
"endpoint_family": "search"
},
"error": {
"code": "page_out_of_range",
"message": "Page 20000 is past the last page of this search."
},
"success": false
}Unknown Area
The `area` value matches no Qasa area (`unknown_area`), or lies in another market than `market` (`area_market_mismatch`). Qasa would ignore it and return every home in the country, so the request is rejected. Up to five suggestions are returned. Non-billable.
{
"meta": {
"attempts": 0,
"billable": false,
"retryable": false,
"endpoint_family": "search"
},
"error": {
"code": "unknown_area",
"message": "Unknown area. Use a name or identifier from /api/qasa/location-autocomplete.",
"suggestions": [
{
"name": "G\u00f6teborg",
"identifier": "se/g\u00f6teborg"
}
]
},
"success": false
}Validation Error
A query parameter is missing, unknown or unusable. Unknown parameters are rejected, never ignored. Non-billable.
{
"errors": {
"market": [
"The selected market is invalid."
]
},
"message": "The selected market is invalid."
}Upstream Unavailable
Qasa could not be reached after retries, answered with an error, or its area list is not available (`upstream_unavailable`, `upstream_blocked`, `parser_drift`, `area_list_unavailable`). Retryable and never billed. Clients are never rate limited.
{
"meta": {
"attempts": 3,
"billable": false,
"retryable": true,
"endpoint_family": "search"
},
"error": {
"code": "upstream_unavailable",
"message": "Qasa is temporarily unavailable. 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.