Find out how your nightly rates compare against nearby listings without spending hours clicking through Airbnb. By the end of this tutorial, you will be able to compare your nightly price against the similar listings in your area.
Short version
- Pick a date range and pull nearby listings with the same bedroom count on the same dates.
- In Nashville, the median price came to $240.
- Save as CSV with room ID, title, bedrooms, rating, total price, per night price and URL.
- Rerun with different dates to get an idea of how your price compares to others.
The Results
We picked this listing to represent your apartment, a two-bedroom condo in Nashville's Gulch priced for 4 adults. Change the link with your own listing to see how it compares.

Your listing
City Retreat: Modern Gulch Pad, Downtown Views!2 bedrooms · 4 beds · 2 baths · ★ 4.85
Nov 8 to Nov 11, 2026 · 3 nights · 4 adults
USD 264/ night
USD 790.89 for 3 nights, fees included
Prices collected November 3, 2026
| Listings | 49 with 2 bedrooms within 1.5 km |
|---|---|
| Median price | USD 240 per night (middle half USD 198 to USD 293) |
| Cheaper than you | 32 of 49 (65%) |
| Per night | Rating | Closest listings by price |
|---|---|---|
| USD 252 | 4.90 | Walk To Broadway!Charming Modern Historic Townhome |
| USD 253 | 4.87 | Step out to Broadway /Cozy Loft with Street Access |
| USD 258 | 4.94 | 1st Floor, No Steps - Walk to Vanderbilt, Belmont |
| USD 261 | 4.88 | HUGE Corner💍GEM-walk to BROADWAY w/pool SLEEPS 8 |
| USD 263 | 4.86 | Walk to Honky Tonks & Broadway |
| USD 264 | Your listing | |
| USD 268 | 4.99 | The Midnight Cowboy | 0.9 Miles to Broadway! |
| USD 269 | 4.76 | The Pink Cowgirl - King Suite |
| USD 269 | 4.84 | Wild Flowers, Wild Horses- Sleeps 8 |
| USD 270 | 4.85 | Luxury Rental with Pool and Hot tub in Music row |
| USD 292 | 4.92 | SoBro 2BR Skyline Views | Pool + Gym |
What you need
- Python 3.11.
- A Tapline account and an API key.
- The Tapline Python client, version 0.2.18:
pip install "tapline==0.2.18". - The listing ID from your Airbnb URL.
Lets run a test request
The code below fetches one page of nearby listings and reads each result's room_id, bedrooms, price.formatted, and name. From this you can get the stay total and extract the average price.
pip install "tapline==0.2.18"export TAPLINE_API_KEY="your-api-key"
import osfrom datetime import date, timedeltafrom tapline import SyncTaplineClientcheck_in = date.today()check_out = check_in + timedelta(days=3)with SyncTaplineClient(api_key=os.environ["TAPLINE_API_KEY"]) as tapline:page = tapline.airbnb.search(lat=36.1580,lon=-86.7766,radius_km=1.5,check_in=check_in.isoformat(),check_out=check_out.isoformat(),adults=4,min_bedrooms=2,)for listing in page.listings[:3]:print(listing.room_id, listing.bedrooms, listing.price.formatted, listing.name)
Run the complete comparison script
This fetches the listing and then finds 2 pages of search results around its location. It drops listings with a different bedroom count and reports how your rate compares to others. Every listing gets saved to a CSV.
"""Compare an Airbnb listing's price with nearby listings for the same dates."""from __future__ import annotationsimport argparseimport csvimport osimport statisticsimport sysfrom dataclasses import asdict, dataclassfrom datetime import date, datetime, timedelta, timezonefrom pathlib import Pathfrom tapline import SyncTaplineClient, TaplineErrorSEARCH_RADIUS_KM = 1.5NUM_SEARCH_PAGES = 2OUTPUT_PREFIX = "airbnb-listings"@dataclass(frozen=True)class Subject:room_id: strtitle: strbedrooms: intlat: floatlng: floatper_night: floatcurrency: str@dataclass(frozen=True)class NearbyListing:room_id: strtitle: strbedrooms: intrating: float | Nonestay_total: floatper_night: floaturl: strdef find_next_stay(tapline: SyncTaplineClient, room_id: str, nights: int) -> date:today = date.today()calendar = tapline.airbnb.get_calendar(room_id=room_id, month=today.month, year=today.year, count=3)days = {day.date: day for month in calendar.months for day in month.days}for offset in range(92):check_in = today + timedelta(days=offset)stay = [days.get((check_in + timedelta(days=night)).isoformat()) for night in range(nights + 1)]if None in stay:continuefirst_night, checkout_day = stay[0], stay[-1]if (first_night.available_for_checkinand (first_night.min_nights or 1) <= nightsand all(day.available for day in stay[:-1])and checkout_day.available_for_checkout):return check_inraise SystemExit(f"Listing {room_id} has no bookable {nights}-night stay in the next 3 months.")def fetch_subject(tapline: SyncTaplineClient, room_id: str, check_in: date, check_out: date, adults: int) -> Subject:details = tapline.airbnb.get_details(room_id=room_id)quote = tapline.airbnb.get_price(room_id=room_id,check_in=check_in.isoformat(),check_out=check_out.isoformat(),adults=adults,)if not quote.available or quote.requested_stay_total is None:raise SystemExit(f"Listing {room_id} is not bookable for {check_in} to {check_out}.")return Subject(room_id=room_id,title=details.title or "",bedrooms=details.bedrooms or 0,lat=details.location.lat,lng=details.location.lng,per_night=quote.requested_stay_total.amount / (check_out - check_in).days,currency=quote.currency,)def fetch_nearby_listings(tapline: SyncTaplineClient, subject: Subject, check_in: date, check_out: date, adults: int) -> list[NearbyListing]:nights = (check_out - check_in).daysnearby: dict[str, NearbyListing] = {}cursor = ""for _ in range(NUM_SEARCH_PAGES):page = tapline.airbnb.search(lat=subject.lat,lon=subject.lng,radius_km=SEARCH_RADIUS_KM,check_in=check_in.isoformat(),check_out=check_out.isoformat(),adults=adults,min_bedrooms=subject.bedrooms,cursor=cursor,)for search_listing in page.listings:if (search_listing.room_id in (None, subject.room_id)or search_listing.bedrooms != subject.bedroomsor search_listing.price.amount is None):continuenearby[search_listing.room_id] = NearbyListing(room_id=search_listing.room_id,title=search_listing.name or search_listing.title or "",bedrooms=search_listing.bedrooms,rating=search_listing.rating,stay_total=search_listing.price.amount,per_night=round(search_listing.price.amount / nights, 2),url=search_listing.url or "",)if not page.pagination.next_cursor:breakcursor = page.pagination.next_cursorreturn sorted(nearby.values(), key=lambda listing: listing.per_night)def find_price_neighbours(subject: Subject, nearby: list[NearbyListing]) -> list[NearbyListing]:cheaper = [listing for listing in nearby if listing.per_night < subject.per_night]pricier = [listing for listing in nearby if listing.per_night >= subject.per_night]return cheaper[-5:] + pricier[:5]def write_csv(nearby: list[NearbyListing], output_dir: Path) -> Path:output_dir.mkdir(parents=True, exist_ok=True)timestamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")output_path = output_dir / f"{OUTPUT_PREFIX}-{timestamp}.csv"with output_path.open("w", newline="", encoding="utf-8") as output:writer = csv.DictWriter(output, fieldnames=list(NearbyListing.__dataclass_fields__))writer.writeheader()for listing in nearby:writer.writerow(asdict(listing))return output_pathdef print_report(subject: Subject, nearby: list[NearbyListing], check_in: date, check_out: date) -> None:per_night = [listing.per_night for listing in nearby]lower, median, upper = statistics.quantiles(per_night, n=4)cheaper = sum(1 for price in per_night if price < subject.per_night)money = subject.currency + " {:,.0f}"print(f"Your listing: {subject.title} ({subject.bedrooms} bedrooms)")print(f"Dates: {check_in} to {check_out}")print(f"Your price: {money.format(subject.per_night)} per night, fees included")print(f"Listings: {len(nearby)} with {subject.bedrooms} bedrooms within {SEARCH_RADIUS_KM} km")print(f"Median price: {money.format(median)} per night "f"(middle half {money.format(lower)} to {money.format(upper)})")print(f"Cheaper than you: {cheaper} of {len(nearby)} ({cheaper / len(nearby):.0%})")print()print("Closest listings by price:")for listing in find_price_neighbours(subject, nearby):rating = f"{listing.rating:.2f}" if listing.rating else "n/a"print(f" {money.format(listing.per_night):>10} {rating:>4} {listing.title[:48]} {listing.url}")def parse_args() -> argparse.Namespace:parser = argparse.ArgumentParser(description=__doc__)parser.add_argument("room_id", help="Your Airbnb listing ID, from its URL")parser.add_argument("--check-in",type=date.fromisoformat,help="Check-in date, YYYY-MM-DD (default: your listing's next bookable stay)",)parser.add_argument("--nights", type=int, default=3, help="Nights to price (default: 3)")parser.add_argument("--adults", type=int, default=2, help="Guests to price for (default: 2)")parser.add_argument("--output-dir",type=Path,default=Path("."),help="Directory for the timestamped CSV (default: current directory)",)return parser.parse_args()def main() -> int:args = parse_args()try:with SyncTaplineClient(api_key=os.environ["TAPLINE_API_KEY"]) as tapline:check_in = args.check_in or find_next_stay(tapline, args.room_id, args.nights)check_out = check_in + timedelta(days=args.nights)subject = fetch_subject(tapline, args.room_id, check_in, check_out, args.adults)nearby = fetch_nearby_listings(tapline, subject, check_in, check_out, args.adults)except TaplineError as error:print(f"Tapline request failed: {error}", file=sys.stderr)return 1if len(nearby) < 4:print(f"Only {len(nearby)} listings found; widen SEARCH_RADIUS_KM.", file=sys.stderr)return 1print_report(subject, nearby, check_in, check_out)print()print(f"Saved {len(nearby)} listings to {write_csv(nearby, args.output_dir)}")return 0if __name__ == "__main__":sys.exit(main())
Download compare_airbnb_prices.py
Going further
The script uses 2 constants: SEARCH_RADIUS_KM: the size of the radius we search through and NUM_SEARCH_PAGES: the number of result pages we consider in our comparison. Increase these parameters to compare your apartment to a broader range of other listings.
Run it on your listing
Run the script with your listing ID and guest count. It prices your listing's next open 3-night stay, or pass --check-in and --nights to pick the dates. It prints the report and writes the CSV to the output directory.
python compare_airbnb_prices.py 41687118 --adults 4
Your listing: City Retreat: Modern Gulch Pad, Downtown Views! (2 bedrooms)Dates: 2026-11-08 to 2026-11-11Your price: USD 264 per night, fees includedListings: 49 with 2 bedrooms within 1.5 kmMedian price: USD 240 per night (middle half USD 198 to USD 293)Cheaper than you: 32 of 49 (65%)Closest listings by price:USD 252 4.90 Walk To Broadway!Charming Modern Historic Townho https://www.airbnb.com/rooms/43800126USD 253 4.87 Step out to Broadway /Cozy Loft with Street Acce https://www.airbnb.com/rooms/560117787898033346USD 258 4.94 1st Floor, No Steps - Walk to Vanderbilt, Belmon https://www.airbnb.com/rooms/547106685230630704USD 261 4.88 HUGE Corner💍GEM-walk to BROADWAY w/pool SLEEPS 8 https://www.airbnb.com/rooms/554429675255632025USD 263 4.86 Walk to Honky Tonks & Broadway https://www.airbnb.com/rooms/770320003270085942USD 268 4.99 The Midnight Cowboy | 0.9 Miles to Broadway! https://www.airbnb.com/rooms/1255204474452570833USD 269 4.76 The Pink Cowgirl - King Suite https://www.airbnb.com/rooms/1378552204561557864USD 269 4.84 Wild Flowers, Wild Horses- Sleeps 8 https://www.airbnb.com/rooms/1346475628817668473USD 270 4.85 Luxury Rental with Pool and Hot tub in Music row https://www.airbnb.com/rooms/33223288USD 292 4.92 SoBro 2BR Skyline Views | Pool + Gym https://www.airbnb.com/rooms/1581455832059843218Saved 49 listings to airbnb-listings-20261103T194817Z.csv
Wrapping Up
And there you have it, save hours of time by leveraging Airbnb data directly instead of manually comparing prices on the website. Want to save even more time? Copy this prompt and have an agent set it up for you!
