pyfunda 2.1.0__tar.gz → 2.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyfunda
3
- Version: 2.1.0
3
+ Version: 2.2.0
4
4
  Summary: Python API for Funda.nl real estate listings
5
5
  Project-URL: Homepage, https://github.com/0xMH/pyfunda
6
6
  Project-URL: Repository, https://github.com/0xMH/pyfunda
@@ -265,6 +265,34 @@ for listing in f.poll_new_listings(
265
265
 
266
266
  This bypasses ES search and queries the detail API directly, catching listings that haven't been indexed yet.
267
267
 
268
+ #### get_price_history(listing)
269
+
270
+ Get historical price data for a listing, including previous asking prices, WOZ tax assessments, and sale history.
271
+
272
+ ```python
273
+ listing = f.get_listing(43032486)
274
+ history = f.get_price_history(listing)
275
+
276
+ for change in history:
277
+ print(change['date'], change['human_price'], change['status'])
278
+ # 22 okt, 2025 €435.000 asking_price
279
+ # 1 jan, 2025 €472.000 woz
280
+ # 19 aug, 2019 €300.000 asking_price
281
+ ```
282
+
283
+ **Returns:** List of price changes, each containing:
284
+
285
+ | Field | Description |
286
+ |-------|-------------|
287
+ | `price` | Numeric price |
288
+ | `human_price` | Formatted price (e.g., "€435.000") |
289
+ | `date` | Human readable date |
290
+ | `timestamp` | ISO timestamp |
291
+ | `source` | "Funda" or "WOZ" |
292
+ | `status` | `asking_price`, `sold`, or `woz` |
293
+
294
+ > **Note:** This fetches data from the Walter Living API. Only called when explicitly requested (lazy-loaded).
295
+
268
296
  ### Listing
269
297
 
270
298
  Listing objects support dict-like access with convenient aliases.
@@ -516,6 +544,29 @@ for listing in f.poll_new_listings(since_id=latest_id, offering_type="buy"):
516
544
 
517
545
  The generator stops after 20 consecutive 404s (configurable via `max_consecutive_404s`).
518
546
 
547
+ ### Get price history for a listing
548
+
549
+ ```python
550
+ from funda import Funda
551
+
552
+ f = Funda()
553
+ listing = f.get_listing(43032486)
554
+
555
+ # Fetch historical prices (WOZ assessments, previous asking prices, sales)
556
+ history = f.get_price_history(listing)
557
+
558
+ print(f"Price history for {listing['title']}:")
559
+ for change in history:
560
+ print(f" {change['date']}: {change['human_price']} ({change['status']})")
561
+
562
+ # Calculate price change over time
563
+ funda_prices = [c for c in history if c['source'] == 'Funda']
564
+ if len(funda_prices) >= 2:
565
+ newest, oldest = funda_prices[0]['price'], funda_prices[-1]['price']
566
+ change_pct = ((newest - oldest) / oldest) * 100
567
+ print(f"\nPrice change: {change_pct:+.1f}%")
568
+ ```
569
+
519
570
  ## License
520
571
 
521
572
  AGPL-3.0
@@ -243,6 +243,34 @@ for listing in f.poll_new_listings(
243
243
 
244
244
  This bypasses ES search and queries the detail API directly, catching listings that haven't been indexed yet.
245
245
 
246
+ #### get_price_history(listing)
247
+
248
+ Get historical price data for a listing, including previous asking prices, WOZ tax assessments, and sale history.
249
+
250
+ ```python
251
+ listing = f.get_listing(43032486)
252
+ history = f.get_price_history(listing)
253
+
254
+ for change in history:
255
+ print(change['date'], change['human_price'], change['status'])
256
+ # 22 okt, 2025 €435.000 asking_price
257
+ # 1 jan, 2025 €472.000 woz
258
+ # 19 aug, 2019 €300.000 asking_price
259
+ ```
260
+
261
+ **Returns:** List of price changes, each containing:
262
+
263
+ | Field | Description |
264
+ |-------|-------------|
265
+ | `price` | Numeric price |
266
+ | `human_price` | Formatted price (e.g., "€435.000") |
267
+ | `date` | Human readable date |
268
+ | `timestamp` | ISO timestamp |
269
+ | `source` | "Funda" or "WOZ" |
270
+ | `status` | `asking_price`, `sold`, or `woz` |
271
+
272
+ > **Note:** This fetches data from the Walter Living API. Only called when explicitly requested (lazy-loaded).
273
+
246
274
  ### Listing
247
275
 
248
276
  Listing objects support dict-like access with convenient aliases.
@@ -494,6 +522,29 @@ for listing in f.poll_new_listings(since_id=latest_id, offering_type="buy"):
494
522
 
495
523
  The generator stops after 20 consecutive 404s (configurable via `max_consecutive_404s`).
496
524
 
525
+ ### Get price history for a listing
526
+
527
+ ```python
528
+ from funda import Funda
529
+
530
+ f = Funda()
531
+ listing = f.get_listing(43032486)
532
+
533
+ # Fetch historical prices (WOZ assessments, previous asking prices, sales)
534
+ history = f.get_price_history(listing)
535
+
536
+ print(f"Price history for {listing['title']}:")
537
+ for change in history:
538
+ print(f" {change['date']}: {change['human_price']} ({change['status']})")
539
+
540
+ # Calculate price change over time
541
+ funda_prices = [c for c in history if c['source'] == 'Funda']
542
+ if len(funda_prices) >= 2:
543
+ newest, oldest = funda_prices[0]['price'], funda_prices[-1]['price']
544
+ change_pct = ((newest - oldest) / oldest) * 100
545
+ print(f"\nPrice change: {change_pct:+.1f}%")
546
+ ```
547
+
497
548
  ## License
498
549
 
499
550
  AGPL-3.0
@@ -5,8 +5,8 @@ Shows previous asking prices, WOZ tax assessments, and sale history
5
5
  using the Walter Living API.
6
6
 
7
7
  Usage:
8
- uv run examples/price_history.py 89666837
9
- uv run examples/price_history.py "https://www.funda.nl/detail/koop/..."
8
+ uv run examples/price_history.py 43032486
9
+ uv run examples/price_history.py "https://www.funda.nl/en/detail/koop/amsterdam/appartement-pieter-calandlaan-400/43032486/"
10
10
  """
11
11
 
12
12
  import argparse
@@ -16,5 +16,5 @@ Example usage:
16
16
  from funda.funda import Funda, FundaAPI
17
17
  from funda.listing import Listing
18
18
 
19
- __version__ = "2.1.0"
19
+ __version__ = "2.2.0"
20
20
  __all__ = ["Funda", "FundaAPI", "Listing", "__version__"]
@@ -18,13 +18,11 @@ API_WALTER = "https://api.walterliving.com/hunter/lookup"
18
18
 
19
19
  # Headers for mobile API
20
20
  HEADERS = {
21
- "user-agent": "Dart/3.9 (dart:io)",
22
21
  "x-funda-app-platform": "android",
23
22
  "content-type": "application/json",
24
23
  }
25
24
 
26
25
  SEARCH_HEADERS = {
27
- "user-agent": "Dart/3.9 (dart:io)",
28
26
  "content-type": "application/json",
29
27
  "accept": "application/json",
30
28
  "referer": "https://www.funda.nl/",
@@ -71,7 +69,7 @@ class Funda:
71
69
  def session(self) -> requests.Session:
72
70
  """Lazily create HTTP session."""
73
71
  if self._session is None:
74
- self._session = requests.Session(impersonate="safari")
72
+ self._session = requests.Session(impersonate="chrome")
75
73
  self._session.headers.update(HEADERS)
76
74
  return self._session
77
75
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "pyfunda"
7
- version = "2.1.0"
7
+ version = "2.2.0"
8
8
  description = "Python API for Funda.nl real estate listings"
9
9
  readme = "README.md"
10
10
  license = "AGPL-3.0-or-later"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes