Hotel Rates, Award Points & OTA Parity — Marriott, Hilton, IHG avatar

Hotel Rates, Award Points & OTA Parity — Marriott, Hilton, IHG

Pricing

from $3.00 / 1,000 api credit units

Go to Apify Store
Hotel Rates, Award Points & OTA Parity — Marriott, Hilton, IHG

Hotel Rates, Award Points & OTA Parity — Marriott, Hilton, IHG

Live room rates, member rates and award points from 11 hotel chains' own booking systems (Marriott Bonvoy, Hilton Honors, World of Hyatt, IHG One Rewards, Choice, Radisson, Wyndham and more), plus the same hotel's price on Booking.com, Expedia, Hotels.com, Trip.com and Agoda: rate parity in one run.

Pricing

from $3.00 / 1,000 api credit units

Rating

0.0

(0)

Developer

Mu0i

Mu0i

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

an hour ago

Last modified

Share

Hotel rates and award points from the chains themselves — and the same hotel's price on the OTAs, side by side. Marriott, Hilton, Hyatt, IHG, Choice, Radisson, Wyndham, Best Western, Meliá, I Prefer and Premier Inn, read from each chain's own booking system at the moment you press Start: every room and rate plan, the member rate, what the night costs in points, and which free-night certificate would cover it. Then Booking.com, Expedia, Hotels.com, Trip.com and Agoda for the same property, compared against the direct rate — rate parity in one run.

The chain data is brand-direct: the numbers the chain's own app and site quote, including member rates and award nights no OTA page shows. The OTA data is there for one reason — to put beside it, so you can see where an OTA undercuts the hotel and by how much.

Output is one flat row per rate plan, per hotel, per night or per channel — ready for CSV, Excel, Google Sheets, or the Apify API.

What you get

Cash ratesEvery room × rate plan for the stay, nightly and stay total, taxes and fees itemised where the chain states them
Member ratesThe loyalty-member price, kept separate from the public rate — never silently mixed into it
Award pointsPoints per night and per stay, points+cash options, any cash co-pay, and cents-per-point against the cash rate for the same stay
Free-night certificatesWhich certificate covers the night and the top-up it needs — Marriott 35k/40k/50k/85k, Hilton free night, IHG 40k
Rate parityThe direct rate beside Booking.com, Expedia, Hotels.com, Trip.com and Agoda for the same hotel: the gap per channel, the cheapest channel, the deepest undercut
Stay vs nightsA multi-night stay sold as one against each night booked alone, and whether a split booking is even possible
Comparable pricesChains publish on different sides of tax. Every row carries the chain's native figure and an after-tax figure, so a cross-chain or chain-vs-OTA comparison is apples to apples
Availabilitysold_out, closed and restricted_los come back as answers, not as empty rows
Freshnesssource and cache_age_sec on every row, so you always know how fresh a number was

Eight modes

ModeOne call doesUse it for
Ratesone hotel × one stay → every room × rate planthe full rate matrix, member rates included
Awardone hotel × one stay → points, points+cash, cents-per-point, certificates"should I pay cash, points or a certificate?"
Calendarone hotel × up to 60 consecutive check-in dates → lowest per nightfinding the cheap dates
Comp setup to 25 hotels × one stay → lowest per hotelyour hotel against its competitors
Comp set (award)up to 25 hotels × one stay → lowest points + cents-per-pointaward sweet spots across a market
Parityone hotel × one stay → direct rate vs up to five OTAswhere an OTA undercuts you, and by how much
Stayone hotel × a 2–14 night stay → the stay as one vs its nights alonewhether to book the stay or night by night
Find hotel codesa city or a map point → the chain's own property codesthe first run, when you don't know the codes yet

How to find a chain's hotel codes

Every other mode takes the chain's own property code — Marriott CHIRL, Hyatt CHIZP, IHG CHIMM, Hilton CHITDHX, Choice IL263. Those codes are not guessable, so Find hotel codes mode exists to produce them: give it a city, an address or a landmark and it returns the chain's hotels around that point with their codes, nearest first.

{ "mode": "find_hotels", "chain": "marriott", "place": "Chicago, IL", "radius": 5 }

One run, one credit ($0.012 — Best Western $0.060, Wyndham $0.072), and you get the whole list however long it is: 35 Marriott codes for Chicago within 5 miles, measured 2026-10-05. Rows carry the code, a distance from your search point, and name, brand, address and coordinates where the chain's own search publishes them (most do; Marriott's returns codes and distances only, so run Rates on a code to see which property it is). You can also search around a point with lat + lng instead of a place name.

Then paste the codes you want into Hotel codes and run any of the other modes.

Rate parity: the direct rate against the OTAs

Give Parity a hotel chain and a code, and it shops the chain's own system and each OTA for the same property, for the same stay, at the same moment. The OTA listing is found for you — the Actor keeps an id map from the chain's code to each OTA's hotel id, filled from Google Hotels' own cross-source match when a hotel is seen for the first time — so you never paste a Booking.com URL. One run on a Choice hotel in Chicago, measured 2026-10-11:

ChannelPublic / night (after tax)vs direct
direct (Choice)118.70—member 106.83, 20,000 points
Booking.com119.76+0.89 %
Expedia97.00−18.28 %
Hotels.com97.00−18.28 %
Agoda119.00+0.25 %
Trip.com——no listing matched

Every run returns the block above as rows: the direct side first, then one row per channel with vs_direct_pct and cheaper, and on every row the verdict (ota_undercuts here), the cheapest channel and the deepest undercut. The comparison is per night after tax — Booking.com's all-in price, Expedia's tax-inclusive one — against the chain's after-tax figure, and public rates only: Genius and Member Price are reported in their own column, as the chain's member rate is, never mixed into the gap. A channel in a different currency is shown but not compared, and the row says so.

Schedule it and the dataset becomes your parity log: filter cheaper = channel for every undercut, by date, by channel.

{ "mode": "parity", "chain": "choice", "hotelCodes": ["IL263"], "checkin": "2026-11-10", "los": 1 }

Pick fewer channels with channels (["booking", "expedia"]); each channel shopped is one Rates call on that OTA, and a channel with no listing for the hotel costs nothing.

The OTAs as sources

The five OTAs are also available as a chain of their own for Rates, Calendar and Comp set — every room and rate plan an OTA lists for a property, with the OTA's own tax-inclusive price. The hotel code is the OTA's hotel id: the number in its URL, or the channel_id a Parity run returns. They carry no award points and no hotel-code search, which is what Parity and the chain modes are for.

Stay or nights?

A three-night stay is sold at one rate, but each of its nights also has a rate of its own — and a hotel with a minimum stay on Saturday will not sell Friday alone. Stay mode shops both at once: the stay as one (row = stay, with the totals), then each night priced alone (row = night, with min_los), and the split verdict — bookable night by night or not, which is cheaper, and the saving.

{ "mode": "stay", "chain": "hilton", "hotelCodes": ["CHITDHX"], "checkin": "2026-11-10", "los": 3 }

Track an award price over time

Award pricing is dynamic at Marriott, Hilton and IHG — the points cost of the same room moves by the night and by the day you ask. One Calendar run on Marriott CHIRL, measured 2026-10-05, priced seven consecutive nights like this:

NightCash (public)Points
2026-11-1045956,000
2026-11-1145956,000
2026-11-1227153,000
2026-11-1322349,000
2026-11-1422350,000
2026-11-1527143,000
2026-11-1645956,000

So to watch a redemption you care about:

  1. Run Award mode for the hotel and date you are tracking, or Calendar mode to see the whole window at once.
  2. Put the Actor on a schedule — every run appends to the same dataset, so the dataset becomes the price history.
  3. Compare points_per_night and cpp between runs. cpp is the cents-per-point value of the redemption against the cash rate for that same stay, so it answers cash or points directly: in the run above, 56,000 points against a $535 after-tax night is 0.96 cents per point.

Free-night certificates

An Award row also says which free-night certificate would cover the night, cheapest first, with the top-up it needs: certs = marriott_50k +6000; marriott_85k means a 50k certificate plus 6,000 points, or an 85k certificate alone. The rules are the programs' published terms — Marriott's 35k/40k/50k/85k awards with up to 15,000 points of top-up, Hilton's free night on any standard reward night, IHG's 40k anniversary night with unlimited top-up. Hyatt certificates are by category, which the chain's pricing does not state, so they are not guessed.

Every run is live at request time (or a cache a few minutes old, which the row tells you), not a nightly snapshot — that is the point of reading the chain's own system rather than a reseller's page.

Which hotel chains and OTAs are supported

Eleven chains, each on its own brand-direct system, and five OTAs.

ChainLoyalty programPublic rateMember rateAward points
MarriottMarriott Bonvoy✓✓✓
HiltonHilton Honors✓✓✓
HyattWorld of Hyatt✓✓✓
IHGIHG One Rewards✓✓✓
ChoiceChoice Privileges✓✓✓
RadissonRadisson Rewards✓✓✓
I PreferI Prefer (Preferred Hotels)✓✓✓
WyndhamWyndham Rewards✓✓—
MeliáMeliá Rewards✓✓—
Best WesternBest Western Rewards✓✓✓
Premier Inn (UK)—✓n/an/a

Points are login-gated at the source on Meliá and Wyndham, and Premier Inn is cash-only. Those columns come back empty rather than estimated.

Wyndham rows name rooms and rate plans by code only — room_code (e.g. ND1) and rate_code (e.g. SWR2P), with room_name and rate_name empty. That is how Wyndham's own booking system answers an anonymous shop: the summary payload carries codes, not names. The prices, the member flag, the tax figures and the availability are complete; only the two name columns are empty, on every Wyndham row, by design. Rate codes are stable per property, so map them once in your sheet.

OTAAs a Parity channelAs a source (Rates, Calendar, Comp set)Member price reported apart
Booking.com✓✓Genius
Expedia✓✓Member Price
Hotels.com✓✓Member Price
Trip.com✓✓—
Agoda✓✓Member deal

How to use it

  1. Pick a mode — start with Rates. (Don't know any hotel codes? Start with Find hotel codes and a city name instead — see above.)
  2. Pick a chain.
  3. Put one or more hotel codes in, one per line. These are the chain's own property codes: Marriott CHIRL, Hyatt CHIZP, IHG CHIMM, Hilton CHITDHX. The input is pre-filled with a working example, so you can press Start straight away.
  4. Set a check-in date and nights, or leave the date empty for 30 days out.
  5. Press Start. Results land in the dataset as flat rows; export as CSV, Excel, JSON or XML, or pull them with the Apify API.

Prefer to do it over HTTP? The same search is GET /v1/hotels?chain=…&q=… on the API — see the API reference.

Use it from your own stack

  • Schedule it. Every run appends to the same dataset, so a daily schedule turns the dataset into a price history — or a parity log.
  • Call it from the Apify API or the JavaScript/Python clients, and export the dataset as JSON, CSV, Excel or XML.
  • Hook it into what you already use — webhooks fire when a run finishes, and the usual integrations (Make, Zapier, Slack, Google Drive) are a few clicks away.
  • Or skip the Actor entirely: the same data is a REST API with an OpenAPI spec — directrate.dev/docs. Sign in at directrate.dev for a key of your own: 250 free credits a month, no card, and a playground to try every call.

Input example

Rates for one Marriott hotel, two nights:

{
"mode": "rates",
"chain": "marriott",
"hotelCodes": ["CHIRL"],
"checkin": "2026-11-10",
"los": 2,
"adults": 2,
"currency": "USD"
}

A comp set — up to 25 hotels answered in one call:

{
"mode": "compset",
"chain": "choice",
"hotelCodes": ["IL263", "IL264", "IL265"],
"checkin": "2026-11-10",
"los": 1,
"compsetRates": "lowest"
}

Award points, cents-per-point and certificates:

{ "mode": "award", "chain": "hyatt", "hotelCodes": ["CHIZP"], "checkin": "2026-11-10", "los": 2 }

A 30-night calendar for one hotel:

{ "mode": "calendar", "chain": "ihg", "hotelCodes": ["CHIMM"], "checkin": "2026-11-10", "calendarDays": 30 }

Parity against two channels only:

{ "mode": "parity", "chain": "marriott", "hotelCodes": ["CHIRL"], "checkin": "2026-11-10", "channels": ["booking", "expedia"] }

Rates straight from an OTA, by its own hotel id:

{ "mode": "rates", "chain": "expedia", "hotelCodes": ["553946"], "checkin": "2026-11-10", "los": 1 }

Output example

One row per rate plan (Rates mode):

{
"chain": "hyatt",
"hotel_code": "CHIZP",
"hotel_name": "Hyatt Place Chicago/Downtown-The Loop",
"checkin": "2026-11-10",
"checkout": "2026-11-12",
"los": 2,
"adults": 2, "children": 0, "rooms": 1,
"status": "available",
"room_name": "1 King, City View",
"rate_name": "Standard Rate", "rate_type": "bar", "member_only": false,
"refundable": true, "meal_plan": "room_only",
"price_per_night": 289.00,
"price_per_night_after_tax": 330.83,
"price_total": 578.00,
"taxes_fees_total": 83.66,
"tax_included": false,
"currency": "USD", "rooms_left": 4,
"lowest_bar": 289.00, "lowest_member": 260.10,
"lowest_bar_after_tax": 330.83, "lowest_member_after_tax": 297.75,
"source": "live", "cache_age_sec": 0, "shopped_at": "2026-11-08T02:31:07Z"
}

Award mode adds points_per_night, points_total, cash_copay, award_type, cpp, the certificates and the cash rate it was compared against:

{
"chain": "marriott", "hotel_code": "CHIRL", "checkin": "2026-11-10", "los": 1,
"status": "available", "award_type": "standard",
"points_per_night": 56000, "points_total": 56000, "cash_copay": null, "taxes_fees": 3.78,
"lowest_points": 56000, "cpp": 1.02,
"certs": "marriott_50k +6000; marriott_85k", "cert_cheapest": "marriott_50k", "cert_top_up": 6000,
"lowest_cash": 479.00, "lowest_cash_after_tax": 569.54, "currency": "USD"
}

Parity mode: one row per side, the direct rate first — this is the Expedia row of the Chicago run above:

{
"chain": "choice", "hotel_code": "IL263", "hotel_name": "Clarion Inn Elmhurst - Oak Brook",
"checkin": "2026-11-10", "los": 1,
"channel": "expedia", "channel_id": "1089", "id_confidence": 0.85, "status": "available",
"public_per_night": 97.00, "public_total": 97.00, "member_per_night": null, "basis": "after_tax",
"rate_name": "pay now", "currency": "USD",
"vs_direct_per_night": -21.70, "vs_direct_pct": -18.28, "cheaper": "channel",
"verdict": "ota_undercuts", "cheapest_channel": "expedia", "cheapest_per_night": 97.00, "max_undercut_pct": 18.28,
"source": "live", "cache_age_sec": 0
}

Reading the price columns

  • price_per_night is in the chain's own tax basis — some chains publish before tax, some after — and tax_included says which. Comparing this column across chains compares different things.
  • price_per_night_after_tax is the comparable figure. Use it for cross-chain and chain-vs-OTA work. It is null only where the source publishes no tax data at all; it is never estimated.
  • price_total is the whole stay. points_per_night and points_total are the award equivalents.
  • In Parity rows, basis says whether the side's figure is after_tax (comparable) or native (the side had no tax data), and vs_direct_pct is the channel's public rate against the chain's, per night.

Pricing

One event: credit-unit = $0.003. A lookup costs a number of units that depends on the chain and what you asked for — you pay for results, not requests.

CallCost
Rates or Award, one hotel (Marriott, Hilton, Hyatt, IHG, Choice, Meliá, Premier Inn, I Prefer)$0.012
Rates, one hotel on an OTA (Booking.com, Expedia, Hotels.com, Trip.com, Agoda)$0.012
Rates or Award, one hotel (Radisson)$0.036
Rates or Award, one hotel (Best Western)$0.060
Rates, one hotel (Wyndham)$0.072
Find hotel codes, one run — however many hotels come back$0.012 (Best Western $0.060, Wyndham $0.072)
Comp set, per hotel returned$0.003 (Radisson / Best Western / Wyndham $0.006), with a minimum of $0.012 per call
Comp set, Guarantee the member rateadds $0.030 per hotel on Radisson, $0.066 on Wyndham and $0.006 on Best Western, where it costs extra upstream calls; no extra on the others
Calendar, per night priced$0.0012 on the hotel chains (Wyndham $0.003); on an OTA, one Rates call per night
Parity, one hotelone Rates call on the chain + one Rates call per OTA that lists the hotel + $0.012 the first time a hotel's OTA ids are looked up. Five channels on a Marriott hotel: at most $0.084, typically less once cached
Stay, one hotelone Rates call on the chain + the Calendar price of its nights
A result served from a recent cachea quarter of the above — the comp-set per-call minimum still applies
An error, a hotel code the chain does not know, or an OTA with no listing for the hotelfree

Worked examples: a 10-hotel Marriott comp set costs $0.03; a 3-hotel one costs $0.012, because that is the per-call minimum rather than 3 × $0.003. A 30-night Hyatt calendar costs $0.036. One Hilton rate matrix costs $0.012. A Parity run on a Choice hotel against all five OTAs, four of them listing it, cost $0.072 live. Set Stop after N credits to cap a run; Apify's own per-run charge limit applies on top.

What your Apify plan already covers

Event charges come out of the platform usage your Apify plan includes, so most runs cost nothing extra:

Your planIncluded usageSingle-hotel lookups it covers
Starter ($19/mo)$19~1,580
Scale ($199/mo)$199~16,500
Business ($999/mo)$999~83,000

On the Apify Free plan this Actor runs in demo mode: a run stops once 5 credits are spent — five single-hotel lookups, or a comp set of about twenty hotels. Enough to see the real output and decide. Any paid plan runs the whole list.

The limit is checked between calls, never inside one, so a single large call runs to completion and is kept in full: a Wyndham lookup (6 credits), a Parity run against all five channels (up to 7 credits), a 60-night Calendar window, or a comp set on Radisson, Wyndham or Best Western each cost more than the cap on their own. What you see then is a run that SUCCEEDED with the rows of that first call complete, a status line "Stopped early: the Apify Free plan limit of 5 credits was reached", and the remaining hotel codes not fetched. That is the demo working as intended, not a failure, and nothing is charged for the calls not made. Keep a demo run to one hotel — or Parity with two channels — and it never trips; a paid Apify plan runs the whole list.

FAQ

Is this official hotel chain API data?

No. There is no partnership with any chain or OTA. The data is read from each chain's and each OTA's own publicly reachable pricing surfaces — the same numbers their app and website quote an anonymous visitor. No account credentials are used and no bookings are placed.

Does it read Marriott's own site, or an OTA?

Both, and it keeps them apart. A Marriott lookup returns Marriott's rate plans, Bonvoy member prices and Bonvoy award nights in points — none of which appear on an OTA page. Parity mode then reads Booking.com, Expedia, Hotels.com, Trip.com and Agoda for the same property and puts their public price beside Marriott's. Every row says which side it came from (chain, or channel in Parity rows).

What is rate parity, and why would an OTA be cheaper than the hotel?

Rate parity is the hotel's promise — to its guests and in its OTA contracts — that its own site is never undercut. It breaks all the time: wholesale rates resold through an OTA, an OTA funding a discount from its own commission, a member price the hotel forgot to match. Parity mode is how a revenue manager finds those cases without opening five tabs per hotel: one run per hotel per date, cheaper = channel filters the undercuts, max_undercut_pct ranks them.

Can I monitor award point prices, or a redemption I am about to book?

Yes — that is what Award and Calendar mode are for, and it is the use case the section above walks through. Schedule the Actor, let the dataset accumulate, and compare points_per_night and cpp run over run. Award pricing at Marriott, Hilton and IHG is dynamic, so the same room genuinely changes points cost between days — and certs tells you when a free-night certificate would cover it.

How is this different from a Booking.com or Expedia scraper?

Those return OTA inventory and OTA prices, and nothing else. This returns what the chain itself quotes, with the OTA price beside it when you ask for it — and three of the columns below exist on no OTA page:

OTA-sourced ActorsThis Actor
Where the number comes froman OTA's listing pagethe chain's own booking system, plus the OTAs on request
Public rate✓✓
Loyalty member rate—✓
Award night in points—✓ (8 of 11 chains)
Cents-per-point, free-night certificates—✓
OTA vs direct gap, per channel—✓
Rate plans (refundable, breakfast, advance purchase)whatever the OTA resellsevery plan the chain sells
Tax basisrarely statedstated per row, plus an after-tax figure

Not legal advice, just the facts about where the data comes from: no account credentials, no logins, no bookings, nothing behind a paywall. The rates are what each chain and each OTA quotes an anonymous visitor on its own public booking surface. No chain or OTA trademark, logo or creative asset is used or resold — their names appear here because they are what the data is about. What you do with the data is yours to square with your own obligations.

Can I get member rates without a loyalty account?

Yes, where the chain quotes them to an anonymous visitor — which most do. They arrive as their own rows with member_only: true and under lowest_member, never folded into the public rate. An OTA's Genius or Member Price is reported the same way, in member_per_night, and never enters the parity gap.

Does it return award / points pricing?

Yes, on 8 of the 11 chains (see the table above), with points_per_night, any cash_copay, cpp — cents per point — computed per night against the after-tax cash rate for the same stay, and the free-night certificates that would cover the night on Marriott, Hilton and IHG.

How fresh are the rates?

Live at request time, or from a cache a few minutes old — every row says which, in source and cache_age_sec. There is no nightly crawl behind this: the numbers are fetched when you press Start, so a points price or a rate that moved an hour ago has already moved here.

How many hotels can one run cover?

Comp-set modes answer up to 25 hotels per call, and a run can make as many calls as you like. Rates, Award, Calendar, Parity and Stay take one hotel per call; give several codes and each is looked up in turn.

Where do I get the hotel codes?

From Find hotel codes mode: a city, address or landmark in, the chain's own codes out. One credit a run — $0.012, or $0.060 on Best Western and $0.072 on Wyndham, whether the search returns three hotels or three hundred. The codes are the chain's internal property identifiers (Marriott calls them MARSHA codes), so they are not guessable and not shared between chains — a Hilton code means nothing to Hyatt. An OTA's code is its own hotel id, which a Parity run returns in channel_id.

Why did a hotel come back as not_found?

The chain does not recognise that property code. Those rows are never charged. sold_out, closed and restricted_los are real answers — the hotel exists, it just isn't selling that stay. In Parity, a channel with skipped set had no listing matched for the hotel (or answered with an error) and is never charged either.

Can I use this on the Apify Free plan?

Yes, in demo mode: a free-plan run stops once 5 credits are spent — five single-hotel lookups, or roughly twenty hotels in a comp set — and the run says so when it stops. That is enough to check the output against a hotel and a date you care about. Any paid Apify plan runs the whole list, with no limit from this Actor beyond the ones you set yourself.

My Free-plan run says "Stopped early" after one hotel — is the data incomplete?

No. The 5-credit demo cap is checked between calls, so the call that crossed it still ran to the end and its rows are all there. A Wyndham lookup or a Parity run against all five OTAs is one call of 6–7 credits, which is over the cap by itself: you get that hotel in full, the run reports Stopped early with the reason, and any further hotel codes in the input are not fetched — and not charged. To fetch several of those in one run, use a paid Apify plan or split them across runs.

Why do my Wyndham rows have no room or rate names?

Because Wyndham's booking system names them by code to an anonymous visitor: every row carries room_code and rate_code, and room_name / rate_name are empty on Wyndham only. Prices, the member flag, taxes, availability and points are all present. It is the source's shape, not a missing lookup — the codes are stable per property, so one mapping in your sheet covers every later run.

Is there an API instead of an Actor?

Yes — the same data is a REST API with an OpenAPI spec: directrate.dev/docs. This Actor is a thin wrapper around it. A key is self-serve at directrate.dev (250 free credits a month, no card); the plans there bill per credit, the same credits this Actor charges.

Something looks wrong — who do I talk to?

Open an issue on the Actor. Every error row carries a request_id; quoting it makes a problem traceable to the exact call.

Good to know before you rely on it

  • No uptime SLA. Chains and OTAs change their systems without notice and a source can degrade for hours. source and cache_age_sec are on every row so you can always see what you got.
  • A live single-hotel lookup typically takes ~1–10 seconds; a 25-hotel comp set and a five-channel Parity run are paced on purpose and can take tens of seconds. Schedule bulk work rather than running it in a request path.
  • Coverage is the eleven chains and five OTAs above — not independents outside those chains, except where an OTA lists them and you shop the OTA directly.
  • A stay that has already started is refused rather than priced: a past check-in date returns an error and costs nothing.
  • Wyndham rows carry room and rate codes without names (the chain publishes codes only); on the Apify Free plan a single Wyndham or five-channel Parity call exceeds the 5-credit demo cap by itself, completes in full, and the run stops there with its rows intact — see the FAQ.