Riyadh Rent Listing Price Delta by District × Category
Date: 2026-09-23
Period: Q1 2025 to Q3 2026, calendar quarters (Q3 2026 is partial: Jul 1 – Sep 22)
Scope: Riyadh (city_id = 21), rent categories (yearly prices), excluding daily-rental booking units
Data Sources: sadb_listings, sadb_categories, sadb_districts
Question: How did the asking rent of new rent listings in Riyadh change quarter by quarter since Q1 2025, when each (district_id, category) cluster is compared only with itself?
Companion report: Riyadh Sale Listing Price Delta.
Executive Summary
Section titled “Executive Summary”- Riyadh asking rents fell 2.6% from Q1 2025 to Q3 2026 (volume-weighted average delta), or −2.1% on the weighted geometric median, across 209 clusters and 183,907 listings. 36% of clusters ended higher than they started.
- Rents declined for four straight quarters (Q2 2025 → Q1 2026), then recovered. The rent index fell from 105.1 to 96.6, was flat in Q2 2026 (+0.1%), and jumped +4.7% in Q3 2026 with the summer moving season. YoY Q3 2026 vs Q3 2025: +1.7%, back to roughly year-ago levels.
- Apartment for Rent (78% of volume): −4.0% since Q1 2025, but flat YoY (+0.2%). The drop has been largest in the northern districts: An Narjis (−8.7%) and Al Malqa (−8.4%). Ar Rimal (+5.5%) rose.
- Big Flat for Rent: −1.6%, and Villa for Rent: −1.2%. Both fell through 2025 and are now slightly above year-ago levels (YoY +1.0% and +2.0%).
- No quarter since Q1 2025 shows broad rent growth before Q3 2026. This is consistent with the Riyadh rent-increase freeze in effect since September 2025. Sale prices fell much more over the same period (−9.4%, see the companion report).
Methodology
Section titled “Methodology”| Choice | Value |
|---|---|
| Listings | city_id = 21, rega_licensed = 1, daily_rentable = 0, price > 0, not deleted |
| Rent periods | rent_period 0 and 3 are yearly prices (same medians); rent_period 2 (monthly) is excluded |
| Quarter | Calendar quarter of create_time (Asia/Riyadh). Q3 2026 covers Jul 1 – Sep 22. |
| Outliers | Per cluster, prices outside the full-period p2–p98 range are dropped |
| Cluster panel | Balanced: only clusters with ≥ 10 listings in every one of the 7 quarters (209 rent clusters covering over 80% of Riyadh rent listings) |
| Weight | Cluster’s total listings over the period |
A balanced panel means every quarter is measured on exactly the same clusters. A district dropping in or out of a quarter can’t show up as a price change.
Estimators for the Q1 2025 → Q3 2026 delta:
- A: weighted mean of average-price deltas. Σ wᵢ·(avg_Q3’26ᵢ/avg_Q1’25ᵢ − 1) / Σ wᵢ. This is the headline “weighted average price delta”.
- C: weighted geometric mean of median ratios. exp(Σ wᵢ·ln(med_Q3’26ᵢ/med_Q1’25ᵢ) / Σ wᵢ) − 1. This is symmetric for rises and falls and resistant to a few extreme clusters.
The quarterly index is Σ wᵢ·(pᵢ,q/refᵢ) / Σ wᵢ × 100, where refᵢ is the cluster’s full-period average. QoQ is index_q / index_q−1 − 1.
Weighted Price Delta by Category
Section titled “Weighted Price Delta by Category”Q1 2025 → Q3 2026, with a same-quarter YoY check (Q3 2026 vs Q3 2025, estimator A). Prices are yearly rent in SAR. Categories with ≥ 5 panel clusters are shown; the “All rent” row includes every category.
| Category | Clusters | Listings | Weighted avg rent (Q1’25 → Q3’26) | A: wavg mean Δ | C: wgeo median Δ | YoY Q3 Δ | % clusters up |
|---|---|---|---|---|---|---|---|
| All rent | 209 | 183,907 | −2.6% | −2.1% | +1.7% | 36% | |
| Apartment for Rent | 91 | 142,959 | 51,484 → 49,171 | −4.0% | −2.6% | +0.2% | 29% |
| Villa for Rent | 29 | 15,966 | 113,754 → 110,690 | −1.2% | −0.8% | +2.0% | 41% |
| Big Flat for Rent | 46 | 15,776 | 71,282 → 70,240 | −1.6% | −1.2% | +1.0% | 37% |
| Office for Rent | 9 | 2,340 | 142,701 → 210,496 | +45.2% | −10.7% | +74.6% | 56% |
| Lounge for Rent | 7 | 1,620 | 75,869 → 80,173 | +6.1% | +0.1% | +11.8% | 43% |
| Building for Rent | 7 | 1,387 | 451,045 → 668,613 | +44.4% | +58.4% | +50.1% | 86% |
| Room for Rent | 5 | 1,258 | 14,148 → 12,377 | −13.4% | −6.9% | −15.4% | 40% |
| Land for Rent | 6 | 932 | 1,346,660 → 1,060,713 | −11.6% | −37.2% | +30.3% | 33% |
| Store for Rent | 5 | 823 | 178,793 → 167,763 | −3.4% | +7.8% | −6.4% | 40% |
Only Apartment, Villa and Big Flat for Rent have enough clusters to be reliable. The commercial categories and Room for Rent have fewer than 10 clusters each, and their estimators often disagree on sign, so treat them as noise. Warehouse (3 clusters) and Complex for Rent (1 cluster) are left out of the table. The Complex cluster has an anomalous Q1 2025 median, which nudges the “All rent” C estimate up by about 0.2 pp.
SQL Query
Section titled “SQL Query”WITH base AS ( SELECT l.district_id, l.category, toStartOfQuarter(toDateTime(l.create_time, 'Asia/Riyadh')) q, toFloat64(l.price) price FROM sadb_listings l FINAL WHERE l._peerdb_is_deleted = 0 AND l.rega_licensed = 1 AND l.daily_rentable = 0 AND l.price > 0 AND l.rent_period NOT IN (1, 2) AND l.district_id > 0 AND l.city_id = 21 AND l.create_time >= toUnixTimestamp(toDateTime('2025-01-01 00:00:00', 'Asia/Riyadh')) AND l.create_time < toUnixTimestamp(toDateTime('2026-09-23 00:00:00', 'Asia/Riyadh')) ), bounds AS ( SELECT district_id, category, quantile(0.02) (price) lo, quantile(0.98) (price) hi FROM base GROUP BY 1, 2 ), trimmed AS ( SELECT b.* FROM base b JOIN bounds x USING (district_id, category) WHERE b.price BETWEEN x.lo AND x.hi ), cq AS ( SELECT district_id, category, q, count() n FROM trimmed GROUP BY 1, 2, 3 ), -- balanced panel: >= 10 listings in all 7 quarters panel AS ( SELECT district_id, category, sum(n) w FROM cq GROUP BY 1, 2 HAVING count() = 7 AND min(n) >= 10 ), cl AS ( SELECT t.district_id district_id, t.category category, any(panel.w) w, avgIf (price, q = '2025-01-01') a0, avgIf (price, q = '2026-07-01') a1, avgIf (price, q = '2025-07-01') y0, medianIf (price, q = '2025-01-01') m0, medianIf (price, q = '2026-07-01') m1 FROM trimmed t JOIN panel USING (district_id, category) GROUP BY 1, 2 )SELECT c.name_en category, count() clusters, sum(w) listings, round(sum(w * a0) / sum(w)) wavg_q1_25, round(sum(w * a1) / sum(w)) wavg_q3_26, round(100 * sum(w * (a1 / a0 - 1)) / sum(w), 1) A_delta, round( 100 * (exp(sum(w * log(m1 / m0)) / sum(w)) - 1), 1 ) C_delta, round(100 * sum(w * (a1 / y0 - 1)) / sum(w), 1) A_yoy_q3, round(100 * countIf (a1 > a0) / count()) pct_upFROM cl JOIN sadb_categories c FINAL ON cl.category = c.category_idWHERE positionCaseInsensitive(c.name_en, 'rent') > 0 -- rent categoriesGROUP BY ROLLUP (c.name_en)ORDER BY listings DESCQuarter-over-Quarter Delta
Section titled “Quarter-over-Quarter Delta”Each value is the weighted rent change from the previous quarter (e.g. Q1’26 = Q1 2026 vs Q4 2025). Cumulative is Q3 2026 vs Q1 2025 on the index. It differs slightly from estimator A above because the index averages normalized rents before dividing, while A averages each cluster’s ratio.
| Category | Q2’25 | Q3’25 | Q4’25 | Q1’26 | Q2’26 | Q3’26* | Cumulative | YoY Q3 |
|---|---|---|---|---|---|---|---|---|
| All rent | −2.9% | −1.6% | −1.2% | −2.7% | +0.1% | +4.7% | −3.7% | +0.7% |
| Apartment for Rent | −2.9% | −1.4% | −1.9% | −3.2% | +0.3% | +4.9% | −4.4% | −0.1% |
| Villa for Rent | −0.9% | −2.7% | +1.0% | −1.8% | +1.2% | +1.2% | −2.0% | +1.6% |
| Big Flat for Rent | −2.9% | +0.1% | −1.9% | −2.6% | +3.0% | +2.3% | −2.1% | +0.7% |
* Q3 2026 is partial (Jul 1 – Sep 22).
Quarterly index (100 = each cluster’s own full-period average):
| Category | Q1’25 | Q2’25 | Q3’25 | Q4’25 | Q1’26 | Q2’26 | Q3’26* |
|---|---|---|---|---|---|---|---|
| All rent | 105.1 | 102.1 | 100.5 | 99.3 | 96.6 | 96.7 | 101.2 |
| Apartment for Rent | 105.5 | 102.4 | 101.0 | 99.1 | 95.9 | 96.2 | 100.9 |
| Villa for Rent | 102.9 | 102.0 | 99.2 | 100.2 | 98.4 | 99.6 | 100.8 |
| Big Flat for Rent | 103.4 | 100.4 | 100.5 | 98.6 | 96.0 | 98.9 | 101.2 |
| Listings (all) | 23,362 | 25,386 | 28,391 | 25,909 | 26,254 | 26,199 | 28,406 |
- Apartment for Rent fell for four straight quarters (Q2 2025 → Q1 2026, −9.1% on the index) and bottomed in Q1 2026, which included Ramadan. It then went flat in Q2 and recovered +4.9% in Q3 2026.
- Q3 2025 did not show the same summer jump (−1.4% for apartments). That makes the +4.9% in Q3 2026 more than a normal seasonal rise, although it only brings rents back to year-ago levels (YoY −0.1%).
- Big Flat for Rent turned up earlier than apartments (Q2 2026, +3.0%). Villa for Rent has moved within ±3% every quarter.
SQL Query
Section titled “SQL Query”-- Same base / bounds / trimmed CTEs as abovecq AS ( SELECT district_id, category, q, avg(price) p, count() n FROM trimmed GROUP BY 1, 2, 3),panel AS ( SELECT district_id, category, sum(n) w, sum(p * n) / sum(n) ref FROM cq GROUP BY 1, 2 HAVING count() = 7 AND min(n) >= 10),j AS ( SELECT cq.category AS cat, cq.q AS q, cq.p AS p, cq.n AS n, panel.w AS w, panel.ref AS ref FROM cq JOIN panel ON panel.district_id = cq.district_id AND panel.category = cq.category JOIN sadb_categories c FINAL ON cq.category = c.category_id WHERE positionCaseInsensitive(c.name_en, 'rent') > 0 -- rent categories),r AS ( SELECT cat, q, 100 * sum(w * p / ref) / sum(w) idx, sum(n) nq FROM j WHERE cat IN (1, 4, 5) GROUP BY cat, q UNION ALL SELECT 0 AS cat, q, 100 * sum(w * p / ref) / sum(w) idx, sum(n) nq FROM j GROUP BY q)SELECT cat, arrayMap( x -> round(x.2, 1), arraySort(groupArray((q, idx))) ) idx_by_quarter, arrayMap(x -> x.2, arraySort(groupArray((q, nq)))) listings_by_quarterFROM rGROUP BY catORDER BY cat -- QoQ = idx[i] / idx[i-1] - 1; Cumulative = idx[Q3'26] / idx[Q1'25] - 1; YoY = idx[Q3'26] / idx[Q3'25] - 1Top Districts per Category
Section titled “Top Districts per Category”The 8 highest-volume panel districts per category. The columns are average yearly asking rents (SAR) per quarter. Δ is Q3 2026 vs Q1 2025, and YoY is Q3 2026 vs Q3 2025.
Apartment for Rent
| District | Listings | Q1’25 | Q3’25 | Q3’26 | Δ | YoY |
|---|---|---|---|---|---|---|
| An Narjis | 13,710 | 65,015 | 61,292 | 59,383 | −8.7% | −3.1% |
| Al Arid | 9,774 | 58,822 | 58,043 | 56,396 | −4.1% | −2.8% |
| Al Malqa | 9,686 | 73,849 | 70,464 | 67,665 | −8.4% | −4.0% |
| Ar Rimal | 6,699 | 40,307 | 38,742 | 42,524 | +5.5% | +9.8% |
| Al Munsiyah | 5,661 | 44,134 | 43,631 | 43,015 | −2.5% | −1.4% |
| Dhahrat Laban | 5,637 | 37,636 | 35,135 | 36,458 | −3.1% | +3.8% |
| Al Yasmin | 5,503 | 65,283 | 61,626 | 62,419 | −4.4% | +1.3% |
| Al Aqiq | 4,423 | 45,807 | 45,502 | 46,698 | +1.9% | +2.6% |
Villa for Rent
| District | Listings | Q1’25 | Q3’25 | Q3’26 | Δ | YoY |
|---|---|---|---|---|---|---|
| An Narjis | 2,152 | 143,945 | 137,400 | 132,942 | −7.6% | −3.2% |
| Al Arid | 1,990 | 126,711 | 107,347 | 113,324 | −10.6% | +5.6% |
| Ar Rimal | 1,812 | 79,699 | 78,240 | 73,832 | −7.4% | −5.6% |
| Al Munsiyah | 1,041 | 109,808 | 119,370 | 133,349 | +21.4% | +11.7% |
| Al Janadriyah | 978 | 64,385 | 62,178 | 62,823 | −2.4% | +1.0% |
| King Khalid International Airport | 838 | 116,665 | 121,523 | 155,558 | +33.3% | +28.0% |
| Al Mahdiyah | 756 | 91,353 | 95,284 | 89,210 | −2.3% | −6.4% |
| Tuwaiq | 634 | 58,508 | 56,729 | 57,342 | −2.0% | +1.1% |
Big Flat for Rent
| District | Listings | Q1’25 | Q3’25 | Q3’26 | Δ | YoY |
|---|---|---|---|---|---|---|
| An Narjis | 1,955 | 83,213 | 82,020 | 88,490 | +6.3% | +7.9% |
| Al Yasmin | 1,313 | 80,531 | 78,071 | 76,517 | −5.0% | −2.0% |
| Al Arid | 1,159 | 76,669 | 78,020 | 75,115 | −2.0% | −3.7% |
| Ar Rimal | 939 | 62,610 | 58,003 | 59,729 | −4.6% | +3.0% |
| Tuwaiq | 581 | 47,686 | 44,638 | 39,618 | −16.9% | −11.2% |
| Badr | 533 | 37,163 | 38,516 | 35,436 | −4.6% | −8.0% |
| Al Munsiyah | 497 | 74,130 | 66,942 | 65,805 | −11.2% | −1.7% |
| Al Malqa | 453 | 118,969 | 103,366 | 101,346 | −14.8% | −2.0% |
SQL Query
Section titled “SQL Query”-- Same base / bounds / trimmed / cq / panel CTEs as the category query, with AND l.category IN (1, 4, 5) in basecl AS ( SELECT t.district_id district_id, t.category category, any(panel.w) w, avgIf (price, q = '2025-01-01') a0, avgIf (price, q = '2025-07-01') y0, avgIf (price, q = '2026-07-01') a1 FROM trimmed t JOIN panel USING (district_id, category) GROUP BY 1, 2),r AS ( SELECT cl.*, row_number() OVER ( PARTITION BY category ORDER BY w DESC ) rk FROM cl)SELECT category, d.district_name_en district, w listings, round(a0) q1_25, round(y0) q3_25, round(a1) q3_26, round(100 * (a1 / a0 - 1), 1) delta, round(100 * (a1 / y0 - 1), 1) yoy_q3FROM r JOIN sadb_districts d FINAL ON r.district_id = d.district_idWHERE rk <= 8ORDER BY category, w DESC