15% off your first purchase with code WELCOME15, up to 25 GB.

See pricing

Travel fares · Hotel content data

Hotel content data collection for mapping and deduplication

Hotel content data collection gathers the descriptive side of a property from public pages: identity, location, room types, amenities, policies and photo metadata. Mapping teams use it to match the same hotel across suppliers and to keep listings accurate; it changes slowly, so it belongs on the cheapest pool.

Pay per GB · No subscription · Prices in EUR, excl. VAT

Illustration. The URLs and values are fictional; the connection string is the real grammar.
€2.00
per GB on ARC Fast, excl. VAT
−44%
at 1 TB (€1.12 / GB)
185+
countries, city targeting
Never
expires — no subscription

Written for

  • OTA content and mapping teams
  • Bed bank supplier-integration teams
  • Metasearch content teams
  • Hotel brand-standards auditors

The short answer

  • Content is not prices: it changes weekly or monthly, does not depend on the visitor's market much, and can run on rotating ISP exits.
  • Where a hotel page carries schema.org structured data (Hotel, LodgingBusiness), it can hold check-in time, amenities, room count and pet policy. Read that first.
  • Store photo metadata (URL, dimensions, perceptual hash), not photos. Hashes are enough for duplicate detection.
  • In the EU, databases can carry a sui generis right, and site terms can restrict extraction from databases the Directive does not protect. Collect only what your use needs.

The problem

What goes wrong without the right IPs

The same hotel under five names

"Hotel Am Markt", "Am Markt Hotel & Spa" and a chain-branded name may be one property. Name matching alone fails; geo-coordinates, address, phone and room count together resolve most cases.

Room types explode across suppliers

One property can show a dozen room names across channels for four physical room types. Mapping needs bed configuration, size, view and occupancy as separate fields.

Amenities without a vocabulary

"Free Wi-Fi", "WiFi (complimentary)" and an icon with no text are the same amenity. Without a controlled vocabulary, amenity filters on your own site return nonsense.

Stale content is worse than none

A pool that closed last year or a pet policy that changed leads to complaints. Change detection on a schedule keeps content honest; a one-off crawl does not.

What to collect

What you can collect

Identity
Name, brand or chain, address, geo-coordinates, business phone, website. The keys for matching.
Classification
Star rating as displayed and its source; property type (hotel, aparthotel, guesthouse).
Room types
Raw room name, bed configuration, size, maximum occupancy, view, bathroom type.
Amenities
Property-level and room-level, raw label and mapped code, and whether stated as included or chargeable.
Policies
Check-in and check-out times, children, pets, deposit, accepted payment, smoking.
Photo metadata
Image URL, dimensions, caption or alt text, perceptual hash. Not the image file.
Provenance
Source URL, fetch time, content hash. Lets you show when a field changed and where it came from.

How it runs

How a collection run works

  1. 01

    Discover properties from sitemaps

    Hotel and chain sites usually list property pages in their sitemaps. Start there instead of paginating search results; it is lighter and complete.

  2. 02

    Read structured data first

    Extract JSON-LD from each page. Where it is present and complete, you need little HTML parsing.

    Pull schema.org Hotel data from a property page
    import json, requestsfrom bs4 import BeautifulSoupPROXIES = {"http": "http://USERNAME_pool-arcfast_country-de:PASSWORD@proxy.arcproxies.io:8000",           "https": "http://USERNAME_pool-arcfast_country-de:PASSWORD@proxy.arcproxies.io:8000"}LODGING = {"Hotel", "LodgingBusiness", "Motel", "Hostel", "Resort", "BedAndBreakfast"}def lodging_jsonld(url: str) -> list[dict]:    html = requests.get(url, proxies=PROXIES, timeout=30).text    out = []    for tag in BeautifulSoup(html, "html.parser").find_all("script", type="application/ld+json"):        try:            data = json.loads(tag.string or "")        except json.JSONDecodeError:            continue        items = data if isinstance(data, list) else data.get("@graph", [data])        for item in items:            types = item.get("@type", [])            types = [types] if isinstance(types, str) else types            if LODGING & set(types):                out.append({k: item.get(k) for k in (                    "name", "address", "geo", "telephone", "starRating", "checkinTime",                    "checkoutTime", "numberOfRooms", "petsAllowed", "amenityFeature")})    return out
  3. 03

    Normalise into your vocabulary

    Map amenity labels and room attributes to your own codes, keep raw values beside them, and record the language of the source page.

  4. 04

    Match and deduplicate

    Block candidates by geo-distance, then score name, address, phone and room count. The techniques are in deduplicating listings.

  5. 05

    Detect changes

    Re-crawl on a schedule, compare content hashes per field, and send only changed fields to review. Most pages will not have changed since last month.

Setup

Recommended setup

Content pages are numerous, static and largely the same for every visitor. Rotating ISP exits are the default; residential is the fallback for sites that serve content only to residential visitors.

PlanRoleSessionTargetingPrice
ARC Basic
Rotating ISP
Default for content crawls
Rotating ISP IPs are the cheapest per GB and fast enough for large, mostly static crawls.
RotatingCountry of the site's main market
€0.75 / GB
€0.59 at 1 TB (−21%)
ARC Fast
Rotating residential
Fallback and language versions
Residential exits for sites that answer ISP ranges poorly, and for collecting the local-language version of descriptions.
Rotating, or sticky per page setCountry
€2.00 / GB
€1.12 at 1 TB (−44%)
ARC Basic — default for content crawls
http://USERNAME_pool-arc_country-de:PASSWORD@proxy.arcproxies.io:8000

Prices are list prices in EUR, excl. VAT. Volume discounts apply automatically at checkout — full ladder on the pricing page.

Connect

One connection string per market

The country, city and sticky session are tokens in the username. Change the token, change the market; keep the session handle, keep the IP.

sticky · Germany · 10 min
http://USERNAME_pool-arcfast_country-de_session-k3f9a1x2_sesstime-10:PASSWORD@proxy.arcproxies.io:8000

Swap _country-de for any market you quote. The full grammar is on the residential proxies page.

Illustration

What a monthly refresh of 200,000 properties costs

An illustration with round numbers — your pages, payloads and retry rate will differ. The arithmetic is the real price ladder.

Assumptions

Properties
200,000
Refresh
monthly
Pages per property
1 (rooms on the same page)
Weight per page, HTML only
600 KB
Bandwidth per month
≈ 120 GB

On ARC Basic

€81.60per month, excl. VAT

120 GB bought in one purchase at €0.68 / GB (−9% volume rung, applied automatically).

The same 120 GB on ARC Fast: €163.20 at €1.36 / GB. Route only the jobs that need it through the pricier pool.

Conditional requests (If-Modified-Since, ETag) and sitemap lastmod dates often let you skip unchanged pages altogether. Never download the images themselves; their URLs and hashes are enough for matching.

Bandwidth never expires, so a bigger single purchase is only ever cheaper per GB. See the ladder.

In depth

Hotel content data, in depth

What hotel pages publish as structured data

Schema.org defines Hotel as a type of LodgingBusiness with properties that map almost one-to-one onto a content model: amenityFeature, availableLanguage, checkinTime (the earliest someone may check in), checkoutTime, numberOfRooms, petsAllowed and starRating, alongside the usual name, address and geo fields.

One caveat matters for amenity data: schema.org notes that amenityFeature does not state whether the feature is included in the offer or available at extra cost. If your product shows "free parking", get that from the page text, not from the structured data.

Content data versus rate data

ContentRates
ChangesWeekly to yearlySeveral times a day
Depends on visitor marketLanguage mostlyYes, see point of sale
Typical poolRotating ISPResidential, sticky per shop
Key riskWrong matches, stale fieldsWrong market, missing restrictions

Keep the two pipelines apart. Rates come from hotel rate shopping; content refreshes on its own slower schedule and feeds the mapping that rate data depends on.

Database rights, site terms and photos

The EU Database Directive gives the maker of a database who has made a substantial investment in obtaining, verifying or presenting its contents a right to prevent extraction or re-utilisation of the whole or a substantial part of it. In Ryanair v PR Aviation (C-30/14, 2015), the Court of Justice held that where a database is protected by neither copyright nor that right, the Directive does not stop the site owner from restricting its use by contract, for example through terms of use.

In practice: collect the fields your matching and accuracy work needs, not entire catalogues for republication; read each site's terms; treat photographs as someone else's work and keep only URLs and hashes. This is a description of the landscape, not legal advice.

Crawling content politely

  • Use sitemaps and lastmod dates instead of re-crawling everything.
  • Honour robots.txt; the reasoning is set out in respecting robots.txt.
  • Send conditional requests and cache aggressively; content that has not changed should cost you nothing.
  • Prefer supplier feeds and content APIs where you have a contract for them, and use public pages to fill gaps and verify.

Works with anything that takes a proxy URL

  • Scrapy
  • Python requests / httpx
  • Crawlee
  • Crawl4AI
  • Docker

FAQ

Questions

Something not covered? Write to contact@arcproxies.io.

What is hotel content mapping?

Hotel content mapping is matching the same property, and its room types, across different suppliers and channels, so one hotel appears once with consistent details. It relies on identity fields such as coordinates, address and phone, plus room attributes.

Do I need residential proxies to collect hotel content?

Usually not. Content pages change slowly and look the same to most visitors, so rotating ISP proxies are the cheaper default. Keep residential exits as a fallback and for local-language versions.

Should I store hotel photos?

Store photo URLs, dimensions, captions and perceptual hashes, not the images. Hashes are enough to detect duplicates and changes, and photographs are someone else's work.

How often should hotel content be refreshed?

Monthly for the full catalogue is common, with a faster cycle for properties that changed recently or have open quality complaints. Use sitemap dates and conditional requests to skip unchanged pages.

Is schema.org data on hotel pages reliable?

It is a good first source, but check it against the visible page. Fields can be out of date, and amenityFeature does not say whether an amenity is free or chargeable.

Sources & review

Last reviewed by the ARC Proxies team. Prices are read from the live catalog at build time.

  1. [1]Schema.org: Hotel (type definition, including properties from LodgingBusiness)
  2. [2]Schema.org: amenityFeature (property definition)
  3. [3]EUR-Lex: Directive 96/9/EC on the legal protection of databases, Article 7
  4. [4]EUR-Lex: Judgment of the Court of 15 January 2015, Ryanair Ltd v PR Aviation BV, Case C-30/14

Travel fares

More on travel fares

OverviewProxies for travel fare aggregationAirline, hotel and rail fares change with the point of sale. Query each market from an IP inside it so the fare you store is the fare a traveller is quoted.Deep diveAirline faresCollect airline fares per point of sale: the same flight priced from each market, taxes itemised, one sticky session per search, billed per GB.Deep diveLow-cost carrier faresMonitor low-cost carrier fares where they are sold: on the airline's own site, priced per leg and per seat bucket, with mandatory fees split out. Per GB.Deep diveAirline ancillary pricesTrack airline ancillary prices (checked bags, seats, priority and fare bundles) per route, date and market, so a trip's true cost can be compared.Deep diveRail and bus faresCollect European rail and intercity coach fares per operator, departure and fare family, including yield-managed long-distance tickets. Billed per GB.Deep diveFerry faresMonitor ferry fares by route, sailing, season and vehicle (foot passengers, cars, cabins) from each operator's own public booking site. Per GB.Deep diveFare alertsBuild fare alerts and deal newsletters on verified prices: cheap watch-list polling, live confirmation from the right market before sending, per-GB costs.Deep diveCorporate travel benchmarkingBenchmark booked and negotiated corporate fares against public fares on the same flights, lead times and markets, for TMCs, travel managers and audits.Deep diveTravel metasearchHow to build a travel metasearch engine: partner feeds, cached prices, live re-pricing and look-to-book. Where proxies fit, and what it costs per GB.Deep diveHotel rate shoppingCollect competitor hotel rates per stay date, length of stay and market from local residential IPs. Sticky sessions per shop, billed per GB.GuideWhy flight prices differ by countryThe same flight costs different amounts in different countries because fares are filed and sold per point of sale, and taxes follow the departure airport.GuideDo airlines raise prices when you search?What regulators and researchers found about cookie and IP tracking in airline pricing, and what actually makes a fare change between two searches.GuideHow often flight prices changeFlight prices can change many times a day: filed fares update constantly and seat availability moves with every booking. What that means for collection.

Get started

Buy a gigabyte and try it on your own targets.

No subscription, no sales call. Code WELCOME15 takes 15% off your first purchase, and whatever you do not use is still there next quarter.