TL;DR
- Poland's EKW (Elektroniczne Ksiegi Wieczyste) is the official land and mortgage register - 25 million property entries across 352 court departments
- There's no API. The portal is a server-rendered JSP application protected by a WAF that blocks all datacenter IPs
- I built an Apify actor that navigates the portal using residential proxies and returns structured JSON for $0.065 per property
- Official court extracts cost 20 PLN (~$5) each. This actor gives you the same data for 10-50x less
Why EKW Has No API
Poland's Elektroniczne Ksiegi Wieczyste is the digital version of the land and mortgage registry maintained by the Ministry of Justice. It covers 25 million property entries managed across 352 court departments (wydzialy ksiag wieczystych) throughout the country. Every apartment, house, plot of land, and commercial building in Poland has a corresponding entry in this registry.
If you work in real estate, banking, or legal services in Poland, you check Ksiegi Wieczyste constantly. Who owns this property? Are there any mortgages? Easements? Restrictions?
The portal at ekw.ms.gov.pl lets you look up one property at a time using a KW number (e.g., WA4M/00012345/6). No bulk access, no export, no API. The system was built as a server-side JSP application - there are no XHR calls, no JSON endpoints, no hidden REST APIs. Every interaction requires filling HTML forms, clicking buttons, and parsing rendered HTML tables.
An official court extract (odpis) costs 20 PLN and requires a formal request. For due diligence on dozens or hundreds of properties, this doesn't scale.
EKW Technical Challenges: WAF, Proxies, Check Digits
WAF Protection Blocks Datacenter IPs
Unlike other Polish government registries (KRS, CRBR, KNF), the EKW portal has a Web Application Firewall that blocks all datacenter IP addresses. Standard proxies, VPNs, and cloud servers all get blocked immediately. AWS, GCP, Azure, Hetzner - all blocked.
The actor requires Polish residential proxies to function. This is the only actor in the entire Polish registry suite with this requirement, which is why the per-query cost is slightly higher than other actors in the series.
KW Number Check Digit Algorithm
KW numbers follow the format XXXX/XXXXXXXX/X where the last character is a check digit validated server-side. If you submit an invalid check digit, the portal rejects the request entirely.
The algorithm uses a character-to-number mapping (A=10, B=11, C=12... X=30, Y=31, Z=32) and a repeating weight pattern [1,3,7,1,3,7,1,3,7,1,3,7]. Each character in the court code and number is converted to its numeric value, multiplied by the corresponding weight, and the results are summed. The check digit is the sum modulo 10.
The actor auto-calculates the check digit if you provide just the court code and number, so you don't need to compute it yourself.
Session and Form Navigation
Because the portal is a traditional JSP application with server-side session state, the actor must maintain cookies and follow the exact form submission sequence the portal expects. Skipping steps or submitting forms out of order results in session errors.
EKW Land Registry Scraper: How to Use
JavaScript (Node.js)
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });
const run = await client.actor('minute_contest/ekw-ksiegi-wieczyste-scraper').call({
kwNumbers: ['WA4M/00012345/6', 'KR1P/00067890/3'],
viewType: 'aktualna', // 'aktualna' = current, 'zupelna' = full history
sections: ['I-O', 'II', 'III', 'IV'], // which sections to extract
proxyConfiguration: { useApifyProxy: true, apifyProxyGroups: ['RESIDENTIAL'] }
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const property of items) {
console.log(`KW: ${property.kwNumber} | ${property.propertyType}`);
console.log(`Court: ${property.courtName}`);
// Section II - Ownership
for (const entry of property.dzialII?.entries || []) {
console.log(` Owner: ${entry.value}`);
}
// Section IV - Mortgages
for (const entry of property.dzialIV?.entries || []) {
console.log(` Mortgage: ${entry.value}`);
}
}
Python
from apify_client import ApifyClient
client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("minute_contest/ekw-ksiegi-wieczyste-scraper").call(
run_input={
"kwNumbers": ["WA4M/00012345/6"],
"viewType": "aktualna",
"sections": ["I-O", "II", "III", "IV"],
"proxyConfiguration": {
"useApifyProxy": True,
"apifyProxyGroups": ["RESIDENTIAL"]
}
}
)
items = client.dataset(run["defaultDatasetId"]).list_items().items
for prop in items:
print(f"KW: {prop['kwNumber']} | {prop.get('propertyType')}")
for entry in prop.get("dzialII", {}).get("entries", []):
print(f" Owner: {entry['value']}")
EKW Property Data: What You Get
The registry is divided into 5 sections, each containing different categories of property information:
| Section | Polish Name | Content |
|---|---|---|
| Dzial I-O | Oznaczenie nieruchomosci | Property designation - area, location, cadastral number, intended use |
| Dzial I-Sp | Prawa zwiazane | Associated rights - e.g., parking spaces, utility easements tied to the property |
| Dzial II | Wlasnosc | Ownership - who owns the property, ownership shares, acquisition basis |
| Dzial III | Prawa i ograniczenia | Rights, restrictions, easements, encumbrances, enforcement claims |
| Dzial IV | Hipoteki | Mortgages - amounts, creditors, currencies, interest rates |
Each section returns structured label-value pairs parsed from the portal's HTML tables. You can select which sections to extract - if you only need ownership data, request just Section II to speed up the scrape.
The viewType parameter controls whether you get the current state (aktualna) or the full history (zupelna) including all past owners, cancelled mortgages, and historical changes.
Real-World Use Case: Portfolio Due Diligence
A private equity fund is evaluating a portfolio of 200 commercial properties in Warsaw for potential acquisition. Before making an offer, they need to verify:
- Current ownership (Section II) - confirm the seller actually owns each property
- Existing mortgages (Section IV) - identify liens that must be cleared at closing
- Restrictions and easements (Section III) - flag properties with enforcement claims or usage restrictions
- Property designation (Section I-O) - verify the area and intended use match the seller's representations
Using the official court process, 200 extracts at 20 PLN each would cost 4,000 PLN (~$1,000) and take days of manual requests. With this actor, the same data costs ~$13 and completes in under an hour.
Who Needs EKW Land Registry Data
- Banks and mortgage lenders - verify property ownership and existing liens before loan approval
- Real estate developers - bulk check properties for encumbrances and restrictions before acquisition
- Law firms - due diligence on real estate transactions, title verification
- Debt collectors - identify debtor assets by searching known property numbers
- Property investors - screen acquisition targets for hidden liabilities and competing claims
EKW Scraper Pricing vs Official Extracts
| Method | Cost per property |
|---|---|
| Official court extract (odpis) | 20 PLN (~$5) |
| Manual portal lookup | Free (one at a time, no export) |
| This actor | ~$0.065 (~0.27 PLN) |
Note: Requires Apify plan with residential proxy access (not available on free tier). The residential proxy requirement is specific to EKW due to its WAF protection.
FAQ
Can I search EKW by address instead of KW number?
No. The EKW portal only accepts KW numbers (e.g., WA4M/00012345/6). There is no address-based search. If you don't know the KW number, you can sometimes find it through the local geodetic office (starostwo powiatowe) or through the geoportal.gov.pl cadastral map.
What is the difference between "aktualna" and "zupelna" view types?
The aktualna (current) view shows only the active state - current owners, active mortgages, and existing restrictions. The zupelna (full) view includes the complete history - all previous owners, cancelled mortgages, and historical changes. The full view takes longer to scrape and produces more data.
How fast can the EKW scraper process properties?
Due to WAF protection and residential proxy requirements, the actor processes approximately 10-20 properties per minute. This is slower than other actors in the suite but still orders of magnitude faster than manual lookups. For large batches (1000+ properties), expect run times of 1-2 hours.
Try it: apify.com/minute_contest/ekw-ksiegi-wieczyste-scraper
This is part of the Polish Business Data APIs series covering programmatic access to Polish government registries.
Top comments (0)