pricewin-hotel-deal-finder

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

PriceWin Hotel Deal Finder

PriceWin酒店优惠查找工具

Compare live hotel prices across Booking.com, Agoda, Google Hotels & OpenTravel in one command — and get back ranked best-value, cheapest, and quality picks with direct booking links.
Stop opening five OTA tabs to find the real cheapest rate. Ask your agent "find me a hotel in Tokyo for 12–15 Aug, 2 guests" and this skill returns a clean, ranked comparison in ~30–60 seconds (cached cities).
Invoke this skill for questions like:
  • "What's the cheapest hotel in
    <city>
    for
    <dates>
    ?"
  • "Is Booking.com or Agoda cheaper for this hotel?"
  • "Compare hotel prices for
    <city>
    ,
    <N>
    guests."
  • "Find me a hotel under $
    <X>
    /night in
    <city>
    ."
  • "Best-value place to stay near
    <landmark>
    on
    <dates>
    ?"
Each returns the same one-command answer below — no clarifying round-trip needed.
What you get from one command:
  • 🥇 Best value · 🥈 Cheapest · 🥉 Quality — picked side-by-side
  • Real per-night prices from up to 4 sources, normalized to USD
  • Clickable booking links straight to the cheapest OTA for each hotel
  • Works for any city worldwide — including bot-hardened ones (Shanghai, Hangzhou, Bangkok…) via a stealth Patchright daemon
  • No API keys, no MCP server —
    node
    /
    npx
    is all you need
Sample result:
🏨 Tokyo • Aug 12–15 • 3 nights • 2 guests
━━━━━━━━━━━━━━━━━━━━
🥇 BEST VALUE
Shinjuku Granbell Hotel
  ✅ agoda      💰 $118/night
     booking    💰 $131/night
     → Save $13 vs Booking
🥈 CHEAPEST
APA Hotel Shinjuku
  ✅ google     💰 $94/night
📊 18 hotels | agoda, booking, google, opentravel • prices in USD
Install:
bash
npx skills add https://github.com/Price-Win/pricewin-skills-hub --skill pricewin-hotel-deal-finder

一键对比Booking.com、Agoda、Google Hotels和OpenTravel的实时酒店价格——并返回按性价比、价格、品质排序的推荐,附带直接预订链接。
无需打开五个OTA标签页寻找真正最便宜的价格。只需向你的Agent询问“帮我找东京8月12-15日的酒店,2位客人”,这个技能会在约30-60秒内返回清晰的排序对比结果(已缓存的城市)。
针对以下类型的问题调用此技能:
  • <城市>
    <日期>
    的最便宜酒店是什么?”
  • “这家酒店在Booking.com和Agoda哪个更便宜?”
  • “对比
    <城市>
    的酒店价格,
    <N>
    位客人。”
  • “帮我找
    <城市>
    每晚低于$
    <X>
    的酒店。”
  • <日期>
    <地标>
    附近性价比最高的住宿是哪里?”
每个问题都会直接返回如下的一站式答案——无需反复确认信息。
一键命令可获得的内容:
  • 🥇 高性价比 · 🥈 最低价 · 🥉 高品质——并列展示
  • 来自最多4个平台的真实每晚价格,统一换算为美元
  • 可点击的预订链接,直接跳转至每家酒店最便宜的OTA平台
  • 支持全球任意城市——包括反爬虫严格的城市(上海、杭州、曼谷……),通过 stealth Patchright daemon实现
  • 无需API密钥,无需MCP服务器——仅需
    node
    /
    npx
    即可使用
示例结果:
🏨 Tokyo • Aug 12–15 • 3 nights • 2 guests
━━━━━━━━━━━━━━━━━━━━
🥇 BEST VALUE
Shinjuku Granbell Hotel
  ✅ agoda      💰 $118/night
     booking    💰 $131/night
     → Save $13 vs Booking
🥈 CHEAPEST
APA Hotel Shinjuku
  ✅ google     💰 $94/night
📊 18 hotels | agoda, booking, google, opentravel • prices in USD
安装方法:
bash
npx skills add https://github.com/Price-Win/pricewin-skills-hub --skill pricewin-hotel-deal-finder

How to use this skill

如何使用此技能

One command does the whole job — you normally won't need to ask clarifying questions first. Infer the parameters (below) and run it:
bash
cd {baseDir} && node bin/search.js "<city>" <checkInYYYY-MM-DD> <checkOutYYYY-MM-DD> <adults> en-us
{baseDir}
is this skill's install directory (auto-resolved by the runtime). If your runtime does not substitute it,
cd
into the folder that contains this
SKILL.md
(the one with
bin/search.js
). Avoid hardcoding a
~/.hermes/...
or
~/.openclaw/...
path — it differs per platform.
Example:
bash
cd {baseDir} && node bin/search.js "Hangzhou" 2026-06-10 2026-06-13 2 en-us
The script handles everything automatically: daemon launch, Agoda cache lookup, Google + Booking inline search, OpenTravel API lookup (all cities), discovery for new cities, and formatted tier-card output. Run it and send the output to the user.
Infer the parameters instead of asking (ask only if the city or dates are genuinely ambiguous):
  • Year: use the current year from today's date unless the user states otherwise. If the requested day/month has already passed this year, assume next year. (Get today's date with
    date +%Y-%m-%d
    if unsure.)
  • "10-13/6"
    <year>-06-10 <year>-06-13
    — fill
    <year>
    from the rule above
  • "2 guests" / "2 people"
    2
    adults
  • Locale: language/region code passed to the OTAs (controls site language + region). Default
    en-us
    . Prices are in USD (Google Hotels is requested with
    gl=us&curr=USD
    ); other sources follow the locale you pass.
One
search.js
run is the whole workflow — no Python, curl, or ad-hoc scraping is needed on top of it.

一键完成全部操作——通常无需先询问确认信息。推断参数(如下)并运行:
bash
cd {baseDir} && node bin/search.js "<city>" <checkInYYYY-MM-DD> <checkOutYYYY-MM-DD> <adults> en-us
{baseDir}
是此技能的安装目录(由运行时自动解析)。如果你的运行时无法自动替换该路径,请
cd
到包含此
SKILL.md
的文件夹(即包含
bin/search.js
的文件夹)。避免硬编码
~/.hermes/...
~/.openclaw/...
路径——不同平台路径不同。
示例:
bash
cd {baseDir} && node bin/search.js "Hangzhou" 2026-06-10 2026-06-13 2 en-us
该脚本会自动处理所有事项:启动daemon、查找Agoda缓存、Google + Booking即时搜索、OpenTravel API查询(所有城市适用)、新城市信息发现,以及格式化的分级卡片输出。运行脚本并将结果发送给用户即可。
主动推断参数而非询问(仅当城市或日期确实模糊时才询问):
  • 年份: 除非用户特别说明,否则使用当前年份。如果用户请求的日/月已过当年,则默认使用下一年。(不确定时可通过
    date +%Y-%m-%d
    获取当前日期。)
  • "10-13/6"
    <year>-06-10 <year>-06-13
    —— 根据上述规则填充
    <year>
  • "2 guests" / "2 people"
    2
    位成人
  • 区域设置: 传递给OTA的语言/地区代码(控制网站语言和区域)。默认值为
    en-us
    。价格以美元显示(Google Hotels请求时使用
    gl=us&curr=USD
    );其他平台会遵循你传递的区域设置。
一次
search.js
运行即可完成整个流程——无需额外使用Python、curl或临时爬虫。

Operating rules — how to get reliable results

操作规则——如何获得可靠结果

RULE 0 — Drive the browser only through
search.js
(via your terminal/shell tool). The native browser tools don't work here.
This skill relies on a stealth Patchright daemon. The runtime's native tools —
browser_navigate
/
browser_open
,
browser_click
,
browser_type
/
browser_fill
,
browser_snapshot
,
browser_close
, any other
browser_*
, and subagent delegation (
delegate_task
/
spawn_agent
) — will fail on this task, so don't reach for them:
  • Those native tools spawn a vanilla Chromium with no stealth, so Booking.com and Agoda detect the bot within seconds; the requests hang until the runtime kills them ("Command timed out after 30/60 seconds"). That burns 5+ minutes and returns nothing. The Patchright daemon that
    search.js
    launches survives bot-detection.
  • Delegated subagents start with empty history and no skill context, so they fall back to Python/curl scraping that gets bot-blocked immediately. Run the skill in the current agent.
The one path that works:
cd {baseDir} && node bin/search.js ...
RULE 1 — Let
search.js
do the scraping; don't scrape an OTA yourself.
Avoid calling
browse.js
directly, doing
goto
/
click
/
type
in the browser, building Agoda/Booking/Google URLs by hand, calling the OpenTravel API separately, or launching the daemon yourself.
search.js
already drives the stealth daemon through a careful flow that survives bot-detection — it handles Agoda discovery internally for EVERY city (including Chinese cities like Shanghai, Hangzhou, etc.). Manually navigating an OTA is the #1 cause of failure: it trips Agoda/Booking anti-bot ("detect automation", "redirect to homepage", "problem completing your search") and gets the IP blocked. Run
search.js
once and send its output. If a source looks "missing", see RULE 4 rather than fetching it by hand.
RULE 2 — First-time city discovery takes 2–4 minutes. If
search.js
output contains
"discovering"
or
"launching"
messages, tell the user: "First time searching this city — discovering selectors, this takes about 2–4 minutes..." and wait for the result rather than retrying or aborting.
RULE 3 — Send the output exactly.
search.js
outputs formatted tier cards ready to send. Copy the output directly into your response. Do not reformat, summarize, or abbreviate it.
RULE 3a — Preserve the markdown hyperlinks. Every hotel name in the output is already wrapped as
[Hotel Name](https://booking-url...)
— a clickable hyperlink. Keep it intact: don't split the URL onto a separate
🔗 https://...
line, don't replace
[Hotel Name](url)
with plain text, keep OTA names lowercase ("google", not "Google"), and keep section titles as-is ("📋 More good deals"). The output is Telegram-MarkdownV2-ready; sending it verbatim gives the user clickable hotel names with hidden URLs (clean UI).
RULE 3b — Hyperlink hotel names in your own commentary too. If you add a suggestion or commentary section after the output, wrap every hotel name you mention as
[Hotel Name](url)
using the same URL the script printed for that hotel, rather than plain text.
RULE 4 — Partial results are normal — send them as-is rather than fixing by hand. A source can be absent from a run (e.g. Agoda blocked this run, or OpenTravel has no inventory for the city). That's fine — send the tier cards with whatever sources are present; the footer (
📊 N hotels | <sources> • prices in USD
) lists exactly what was found. Fetching the missing source via the browser or a direct URL tends to trip anti-bot and make things worse, so avoid it. If
search.js
errors out entirely, tell the user what failed in one line and show any partial output it printed above the error. For more coverage, the one reliable retry is running the same
search.js
command again (anti-bot is often transient).

规则0 — 仅通过
search.js
(终端/Shell工具)驱动浏览器。原生浏览器工具在此无效。
此技能依赖stealth Patchright daemon。运行时的原生工具——
browser_navigate
/
browser_open
browser_click
browser_type
/
browser_fill
browser_snapshot
browser_close
及其他
browser_*
工具,以及子Agent委托(
delegate_task
/
spawn_agent
)——都会导致任务失败,请不要使用:
  • 这些原生工具会启动无隐身配置的Chromium,因此Booking.com和Agoda会在数秒内检测到机器人,请求会一直挂起直到运行时终止(“命令超时30/60秒”)。这会浪费5分钟以上时间且毫无结果。
    search.js
    启动的Patchright daemon可以避开反爬虫检测。
  • 委托的子Agent启动时无历史记录和技能上下文,因此会退回到Python/curl爬虫,立即被反爬虫拦截。请在当前Agent中运行此技能。
唯一可行的方式:
cd {baseDir} && node bin/search.js ...
规则1 — 让
search.js
处理爬虫;不要自行爬取OTA内容。
避免直接调用
browse.js
、在浏览器中执行
goto
/
click
/
type
操作、手动构建Agoda/Booking/Google URL、单独调用OpenTravel API,或自行启动daemon。
search.js
已经通过精心设计的流程驱动隐身daemon,能够避开反爬虫检测——它会自动处理所有城市(包括上海、杭州等中国城市)的Agoda信息发现。手动访问OTA是失败的首要原因:会触发Agoda/Booking的反机器人机制(“检测到自动化操作”“重定向至首页”“搜索无法完成”),导致IP被封禁。运行一次
search.js
并发送其输出即可。如果某个平台的数据缺失,请查看规则4,而非手动获取。
规则2 — 首次搜索新城市需要2-4分钟。 如果
search.js
的输出包含"discovering"或"launching"信息,请告知用户:“首次搜索该城市——正在发现选择器,此过程约需2-4分钟……”,等待结果返回,不要重试或中止。
规则3 — 完全原样发送输出内容。
search.js
输出的格式化分级卡片可直接发送给用户。直接复制输出内容到回复中,不要重新格式化、总结或缩写。
规则3a — 保留Markdown超链接。 输出中的每个酒店名称都已包装为
[酒店名称](https://预订链接...)
——即可点击的超链接。请完整保留:不要将URL拆分到单独的
🔗 https://...
行,不要将
[酒店名称](url)
替换为纯文本,保持OTA名称小写(如"google"而非"Google"),并保持章节标题不变(如"📋 More good deals")。输出内容符合Telegram-MarkdownV2格式;原样发送可为用户提供带有隐藏URL的可点击酒店名称(界面简洁)。
规则3b — 在自定义评论中也为酒店名称添加超链接。 如果在输出内容后添加建议或评论部分,请使用脚本为该酒店提供的相同URL,将提到的每个酒店名称包装为
[酒店名称](url)
,而非纯文本。
规则4 — 部分结果是正常情况——原样发送,不要手动修复。 某次运行中可能缺少某个平台的数据(例如Agoda本次运行被拦截,或OpenTravel在该城市无库存)。这是正常的——发送包含现有平台数据的分级卡片即可;页脚(
📊 N hotels | <有数据的平台> • prices in USD
)会准确列出已获取的平台。通过浏览器或直接URL获取缺失平台的数据往往会触发反爬虫机制,导致情况恶化,因此请避免这样做。如果
search.js
完全报错,请用一句话告知用户失败原因,并显示报错上方的所有部分输出内容。如需覆盖更多情况,唯一可靠的重试方式是再次运行相同的
search.js
命令(反爬虫拦截通常是暂时的)。

Output Format Reference

输出格式参考

search.js
prints tier cards in this format — you send this directly to the user:
The hotel name is a Markdown link to its cheapest OTA. Price rows carry NO links and the OTA key is shown lowercase (
agoda
/
booking
/
google
/
opentravel
). There are no star ratings or area lines — the script does not have that data.
🏨 <city> • <d1>–<d2> • <N> nights • <adults> guests
━━━━━━━━━━━━━━━━━━━━

🥇 BEST VALUE
[<Hotel Name>](<cheapest_link>)
  ✅ agoda      💰 <price>/night
     booking    💰 <price>/night
     opentravel 💰 <price>/night
     → Save <diff> vs Booking

🥈 CHEAPEST
[<Hotel Name>](<cheapest_link>)
  ✅ google     💰 <price>/night
     agoda      💰 <price>/night

🥉 QUALITY
[<Hotel Name>](<cheapest_link>)
  ✅ booking    💰 <price>/night
     agoda      💰 <price>/night

📋 More good deals
  — Agoda —
  • [<Hotel>](<agoda_link>) — agoda: <price> | booking: <price>
  — Booking —
  • [<Hotel>](<booking_link>) — booking: <price>
  — Google —
  • [<Hotel>](<google_link>) — google: <price>
  — OpenTravel —
  • [<Hotel>](<opentravel_link>) — opentravel: <price>

💡 Tip: <best Hotel Name>
   [Book on <OTA>](<link>) — <price>/night

📊 <N> hotels | <sources with data> • prices in USD
All prices are shown in USD. Agoda, Google and OpenTravel geo-lock to VND by IP and are converted via a live FX rate; Booking returns USD natively. Only sources that actually returned data are listed in the footer.

search.js
会按以下格式打印分级卡片——直接发送给用户即可:
酒店名称是指向其最便宜OTA平台的Markdown链接。价格行不包含链接,OTA标识显示为小写(
agoda
/
booking
/
google
/
opentravel
)。输出中没有星级评分或区域信息——脚本无此类数据。
🏨 <city> • <d1>–<d2> • <N> nights • <adults> guests
━━━━━━━━━━━━━━━━━━━━

🥇 BEST VALUE
[<Hotel Name>](<cheapest_link>)
  ✅ agoda      💰 <price>/night
     booking    💰 <price>/night
     opentravel 💰 <price>/night
     → Save <diff> vs Booking

🥈 CHEAPEST
[<Hotel Name>](<cheapest_link>)
  ✅ google     💰 <price>/night
     agoda      💰 <price>/night

🥉 QUALITY
[<Hotel Name>](<cheapest_link>)
  ✅ booking    💰 <price>/night
     agoda      💰 <price>/night

📋 More good deals
  — Agoda —
  • [<Hotel>](<agoda_link>) — agoda: <price> | booking: <price>
  — Booking —
  • [<Hotel>](<booking_link>) — booking: <price>
  — Google —
  • [<Hotel>](<google_link>) — google: <price>
  — OpenTravel —
  • [<Hotel>](<opentravel_link>) — opentravel: <price>

💡 Tip: <best Hotel Name>
   [Book on <OTA>](<link>) — <price>/night

📊 <N> hotels | <sources with data> • prices in USD
所有价格均以美元显示。Agoda、Google和OpenTravel会根据IP自动锁定为VND,通过实时汇率转换为美元;Booking原生返回美元价格。页脚仅列出实际返回数据的平台。

Limitations

局限性

  • First search per city pays the Agoda discovery cost (2–4 minutes). Google and Booking are inline (no discovery); OpenTravel is a direct API call.
  • Subsequent searches reuse the Agoda cache and complete in ~30–60 seconds.
  • 首次搜索某城市需承担Agoda信息发现成本(2-4分钟)。Google和Booking为即时搜索(无需信息发现);OpenTravel为直接API调用。
  • 后续搜索会复用Agoda缓存,约30-60秒即可完成。

Security & data handling

安全与数据处理

Runs locally, needs no API keys, and collects no personal data — the only data sent out is the search query (city, dates, guests). Scraped hotel text is treated as untrusted:
sanitizeText()
in
bin/search.js
strips control/zero-width/bidi and markdown-control characters before any of it reaches model output, and booking links are restricted to
http(s)
. Full disclosure of commands run, downloads, and network egress is in
SECURITY.md
.
本地运行,无需API密钥,不收集任何个人数据——仅发送搜索查询(城市、日期、客人数量)。爬取的酒店文本被视为不可信内容:
bin/search.js
中的
sanitizeText()
函数会在内容进入模型输出前,移除控制字符、零宽字符、双向字符和Markdown控制字符;预订链接仅限制为
http(s)
协议。有关运行命令、下载内容和网络出口的完整披露,请查看
SECURITY.md