Small Python scraper for checking Hilton flexible-date award availability.
It is currently configured for SJOTTLX and PPTBNCI, but the hotel codes can
be changed in SEARCHES.
The script launches Google Chrome with a temporary Chrome DevTools Protocol profile, opens Hilton's flexible-date calendar, captures the calendar JSON responses, and prints reward availability for the configured target dates.
Install the Python dependency:
python3 -m pip install -r requirements.txtLocally, the script looks for Google Chrome at:
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome
It also checks common Linux Chrome/Chromium paths and the CHROME_PATH
environment variable. If Chrome is somewhere else, set chrome_path in a
search config.
Edit SEARCHES in hilton_award_finder.py.
Example:
SEARCHES = (
build_segment_searches(
hotel="SJOTTLX",
stay_start="2026-12-28",
stay_end="2027-01-02",
)
+ [
{
"hotel": "PPTBNCI",
"arrival": "2027-07-03",
"target_dates": ["2027-07-03", "2027-07-04", "2027-07-05"],
"nights": 5,
"adults": 1,
"standard_only": True,
}
]
)Notes:
arrivalanchors the Hilton flexible-date month that will be loaded.target_datescontrols which dates are printed from that returned month.build_segment_searchesenumerates every valid 1-, 2-, 3-, 4-, and 5-night stay segment inside the requested stay window by default. Setmax_nightsto use a shorter maximum stay length.- Leave
target_datesempty to inspect the whole month. standard_only=Truestill prints all target dates, then summarizes standard room reward count and the lowest available reward.- Multiple entries in
SEARCHESrun sequentially by default for Chrome/CDP reliability. IncreaseMAX_CONCURRENT_SEARCHESonly if your environment can launch multiple Chrome instances cleanly. - Each search gets a unique generated label unless you provide
label; debug artifacts use that label so searches for the same hotel/month do not overwrite each other. - Use
alert_groupandalert_required_dateswhen an email should only be sent after a full stay can be covered by a non-overlapping combination of standard reward segments. - Omit
alert_groupto email when any configured stay segment has a standard reward. The SJOTTLX holiday search uses this behavior.
SJOTTLX: 2026-12-28 to 2027-01-02. The script searches every valid 1-, 2-, 3-, 4-, and 5-night stay and emails if any one of them has a standard reward.PPTBNCI: five-night stays arriving 2027-07-03, 2027-07-04, or 2027-07-05 for one adult. The script emails if any one has a standard reward.
python3 hilton_award_finder.pyThe script prints a table for each configured search and writes parsed JSON to
results/.
The workflow in .github/workflows/hilton.yml runs the search automatically
every 30 minutes and can also be triggered manually from the GitHub Actions UI.
- Open the repo on GitHub.
- Go to Actions.
- Enable workflows if GitHub asks for confirmation.
The workflow sends email when an alert condition is met. Standalone searches alert when a configured target date has a standard reward. Grouped searches, when configured, alert only when standard reward segments can be combined into a complete stay with no gaps.
Add these repository secrets under Settings -> Secrets and variables -> Actions:
EMAIL_USERNAME: Gmail address used to send email.EMAIL_PASSWORD: Gmail app password.EMAIL_TO: optional recipient address. If omitted,EMAIL_USERNAMEis used.
Manual run:
Actions -> Hilton Reward Search -> Run workflow
The workflow uploads results/ and debug/ as a run artifact for inspection.
GitHub-hosted runners use data-center IPs, so Hilton may occasionally block or challenge a run even when the local script works. Check the uploaded debug artifact if a scheduled run captures no rewards.
Generated files are intentionally ignored by git:
results/contains parsed search output.debug/contains captured HTML, screenshots, response JSON, and diagnostics.- Local Chrome/CDP profile folders are also ignored.
If Hilton changes the page or blocks a run, check the files in debug/ for the
captured page state and network diagnostics.
.
├── hilton_award_finder.py # Main scraper script
├── requirements.txt # Python dependencies
├── README.md
├── .gitignore
├── .github/
│ ├── workflows/
│ │ └── hilton.yml # Scheduled/manual GitHub Actions workflow
│ └── scripts/
│ └── summarize.py # Workflow result summary and email body
├── results/ # Generated parsed output, ignored by git
└── debug/ # Generated diagnostics, ignored by git