【半自动轮椅♿️】分享一个AA搜JL票脚本,我太太太奶奶都会用
半自动AA搜票脚本绕过风控的核心操作与限制。
1. 关键信息
- 需从Chrome Console运行JavaScript代码,依赖当前Session的Cookie与credentials。
- 禁403/400主要因请求过快或浏览器profile重复,建议500ms-3s延迟。
- 一次扫描强制整月(calendar API限制),每日日期可改但易触发风控。
- 被封后换浏览器profile或IP可解,通常约一天(#1, #11, #14, #16, #45, #50, #55)。
- 进阶方案:ip pool + 自动化浏览器 + Telegram/Discord通知 + 改用Python/Selenium(#53, #55, #56)。
2. 羊毛/优惠信息
无。
3. 最新动态
- 作者已提供免Code的Bookmarklet/GreaseMonkey插件,简化至点击安装运行(#32)。
4. 争议或不同意见
- 有人质疑全自动在Akamai下极易触发Challenge,shell/python难绕过,必须用自动化浏览器(#24, #55, #56)。
- 有人反映即使控制间隔仍被ban,怀疑与profile或Akamai算法有关(#11, #16, #50)。
5. 行动建议
- 小白使用提供的Bookmarklet;进阶用户可叠加ip pool与自动化浏览器。
- 扫描时控制请求间隔,优先在非高峰时段操作,避免频繁触发风控。
去年AA大幅增强风控,导致之前大佬分享的全自动脚本不再能用,会一直报错说access blocked。
【引用自 未知】:
【真】全自动AA搜票工具,我太奶奶都会用 航空常旅客
拜读过 0基础用Python和Postman搜里程票教程 - 旅行 / 航空常旅客 - 美卡论坛 之后,深受启发,但与此同时感到虽然 @smb 大佬已经尽量嚼碎了喂饭给大家,这里还是有些技术门槛在的。为此,我将其包装起来,供大家更方便使用。
需求
google 账号
浏览器(手机/电脑/anywhere)
使用步骤
点开 Google Colab
[image]
右上角登录Go…
基于这个稍微改了几个版本,这里分享个半自动,但也是用起来最最方便的轮椅,至少大家能自己动手丰衣足食
原理其实很简单,现在搜票api不能单独发了,需要cookie和credentials,我们直接从chrome里偷来发api reqest。
注意事项
还是不能发太多request,暂时没试出来准确limit,同ip发多了会被封ip+brower,换个brower能破。被封的过段时间也会自己解开,具体时间不记得了,好像是一天?
这个需要手动自己每次跑,跑的时候重新execute。也可以改成loop,但是cookie可能会过期,而且被封的概率大幅增加
使用步骤
打开 aa.com
F12打开console,第一次execute command 需要手动允许一下
复制这段代码跑就行了,记得改下参数, 在最上面几行,比较self explanatory。 主要就是改你的起飞机场和日期
// === AA Award Calendar Scanner - Run in browser console on aa.com ===
(async function() {
// ================== CONFIGURATION ==================
const fromYear = 2026;
const fromMonth = 2; // January = 1
const toMonth = 1; //
const origins = ['JFK', 'TYO'];
const destinations = ['TYO', 'JFK'];
const cabin = 'BUSINESS,FIRST'; // Options: "COACH", "PREMIUM_COACH", "BUSINESS,FIRST"
const maxStops = '1'; // "0", "1", "2"
const includeLink = true;
const delayMs = 300; // Delay between requests (ms) - do not set to 0
// ===================================================
const TYO = new Set(['NRT', 'HND']);
function isSameCity(a, b) {
return a === b || (TYO.has(a) && TYO.has(b));
}
// Build list of dates to query (first day of each month)
const dates = [];
for (let year = fromYear; year <= (fromMonth <= toMonth ? fromYear : fromYear + 1); year++) {
const startM = year === fromYear ? fromMonth : 1;
const endM = year === fromYear && fromMonth <= toMonth ? toMonth : (year > fromYear ? toMonth : 12);
for (let month = startM; month <= endM; month++) {
dates.push(`${year}-${String(month).padStart(2, '0')}-01`);
}
}
console.log(`Starting scan: ${dates.length} months × ${origins.length} origins × ${destinations.length} destinations / 2 (roundtrip) = ${dates.length * origins.length * destinations.length/2} total requests`);
const results = [];
let totalRequests = 0;
for (const depDate of dates) {
for (const origin of origins) {
for (const dest of destinations) {
if (isSameCity(origin, dest)) continue;
totalRequests++;
await new Promise(r => setTimeout(r, delayMs));
let foundInThisMonth = 0;
try {
const response = await fetch("https://www.aa.com/booking/api/search/calendar", {
"headers": {
"accept": "application/json, text/plain, */*",
"accept-language": "en-US",
"content-type": "application/json",
"cache-control": "no-cache",
"pragma": "no-cache",
"priority": "u=1, i",
"sec-ch-ua": "\"Chromium\";v=\"142\", \"Google Chrome\";v=\"142\", \"Not_A Brand\";v=\"99\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"macOS\"",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin"
},
"referrer": "https://www.aa.com/booking/choose-flights",
"body": JSON.stringify({
"metadata": { "selectedProducts": [], "tripType": "OneWay", "udo": {} },
"passengers": [{ "type": "adult", "count": 1 }],
"requestHeader": { "clientId": "AAcom" },
"slices": [{
"allCarriers": true,
"cabin": cabin,
"departureDate": depDate,
"destination": dest,
"destinationNearbyAirports": false,
"maxStops": maxStops,
"origin": origin,
"originNearbyAirports": false
}],
"tripOptions": {
"corporateBooking": false,
"fareType": "Lowest",
"locale": "en_US",
"pointOfSale": null,
"searchType": "Award"
},
"loyaltyInfo": null,
"version": "",
"queryParams": { "sliceIndex": 0, "sessionId": "", "solutionSet": "", "solutionId": "" }
}),
"method": "POST",
"mode": "cors",
"credentials": "include"
});
if (!response.ok) {
console.log(`⚠️ ${depDate} ${origin}→${dest}: HTTP ${response.status} (skipped)`);
continue;
}
const data = await response.json();
for (const month of data.calendarMonths || []) {
for (const week of month.weeks || []) {
for (const day of week.days || []) {
if (!day.validDay) continue;
const solution = day.solution;
if (solution && solution.perPassengerAwardPoints < 100000) {
foundInThisMonth++;
const bookUrl = `https://www.aa.com/booking/search?type=OneWay&searchType=Award&from=${origin}&to=${dest}&pax=1&cabin=${cabin}&locale=en_US&nearbyAirports=false&depart=${day.date}&carriers=ALL&pos=US&adult=1`;
// Detailed find with full link
console.log(`🎯 Found: ${day.date} (${new Date(day.date).toLocaleDateString('en-US', { weekday: 'short' })}) ${origin}→${dest} | ${solution.perPassengerAwardPoints.toLocaleString()} points + $${solution.perPassengerSaleTotal?.amount || 0} | ${bookUrl}`);
results.push({
date: day.date,
route: `${origin} → ${dest}`,
dayOfWeek: new Date(day.date).toLocaleDateString('en-US', { weekday: 'short' }),
points: solution.perPassengerAwardPoints.toLocaleString(),
cash: solution.perPassengerSaleTotal?.amount || 0,
currency: solution.perPassengerSaleTotal?.currency || 'USD',
link: includeLink ? `<a href="${bookUrl}" target="_blank">Book</a>` : ''
});
}
}
}
}
} catch (err) {
console.log(`💥 Error on ${depDate} ${origin}→${dest}: ${err.message}`);
}
// === PROGRESS UPDATE FOR THIS MONTH/ROUTE ===
if (foundInThisMonth > 0) {
console.log(`✅ ${depDate} ${origin}→${dest}: Found ${foundInThisMonth} award dates`);
} else {
console.log(`❌ ${depDate} ${origin}→${dest}: No availability`);
}
}
}
}
// ============= DISPLAY FINAL RESULTS =============
console.log(`\nScan complete! Processed ${totalRequests} requests.`);
if (results.length === 0) {
document.body.insertAdjacentHTML('beforeend', '<h2 style="color:orange">No award availability found in the scanned period 😔</h2>');
return;
}
results.sort((a, b) => a.date.localeCompare(b.date));
let tableHTML = `
<h2 style="color:green">🎉 Found ${results.length} Award Opportunities!</h2>
<p><strong>Scanned period:</strong> ${dates[0]} to ${dates[dates.length-1].slice(0,7)}-31</p>
<table border="1" cellpadding="8" cellspacing="0" style="border-collapse:collapse; font-family:Arial; background:white; margin-top:20px;">
<thead style="background:#f0f0f0">
<tr>
<th>Date</th>
<th>Day</th>
<th>Route</th>
<th>Points</th>
<th>+ Cash</th>
<th>Link</th>
</tr>
</thead>
<tbody>`;
for (const r of results) {
tableHTML += `
<tr>
<td>${r.date}</td>
<td>${r.dayOfWeek}</td>
<td>${r.route}</td>
<td style="text-align:right; font-weight:bold">${r.points}</td>
<td style="text-align:right">${r.cash} ${r.currency}</td>
<td>${r.link}</td>
</tr>`;
}
tableHTML += `</tbody></table>`;
document.body.insertAdjacentHTML('afterbegin', tableHTML);
console.log(`${results.length} total awards displayed in table above.`);
})();
效果演示
Screenshot 2026-01-02 at 5.55.55 AM1920×1013 403 KB
希望大家新年都能找到属于自己的票!
【引用自 AnonAno】:
ip+brower
捉个虫 感觉应该是browser(?)
大半夜写的有点神智不清 感谢错字侠出警
牛的兄弟
感谢!找AI改成了bookmarklet,放在书签栏点击运行。
强! 我今天点赞到上限了…
不介意的话可以分享下,我link进主楼
估计还有很多能优化的地方 晚点我再改改!
昨晚我太太太奶奶托梦让我烧一台好点的电脑下去。
竟然还有上限!从来没到过,上限是多少?
y/m/d里的day是不是还要改一下 现在貌似hard code成只搜每个月1号?
hmm 我发的这个版本脚本loop可能没问题,但也不推荐,因为我自己也被block过
我还有一版是会去qurey individual flight 去看机型,那个很容易死。两圈下来可能也就200个request 5min,大概跑十几分钟就无了。不知道是不是我哪里写的有问题。
他们用的好像是akami有点随机 我一直找不到规律
我其实问的是点赞上限
哦哦 你说点赞吗(
我是50 可能我等级太菜了
我设置5秒一次,origin和destination 没动总共24个query,到第11个月的时候就被ban了(400)
只能说NB
loop的话是很有可能ban,但也玄学。这十一个月就ban可能倒霉吧…
不对,看了眼我截图但我好像12月也有400,但我怎么感觉可能是哪里有bug…你再跑一圈试试,有没有成功的? ban应该是access denied 403,而且网页上也会白屏写access denied
请允许我问一个小白问题,打开F12去哪里跑这个command?我找到了run - command, 没用啊
打开后右手边最上面or中间应该有个bar可以选tab,选console,滚到最下面有个地方能打字,复制到那里面后按enter。
如果chome console是第一次跑代码跑会报错,会说要你手动输入一行啥,我不记得了。输入后再复制进去跑一次就行
Screenshot 2026-01-02 at 9.26.25 AM2428×418 93.5 KB
Screenshot 2026-01-02 at 9.25.16 AM2416×378 76.2 KB
我因为用的是incognito,之前关了,又开了个新的是能跑的
没什么好说的,牛就一个字!
这什么银卡小号冲钛帖?
我记得之前有一段时间手动刷都ban
如果可以做到tampermonkey里一键爬应该就是全自动了 ,再加个interface
大佬又开小号冲钛啦
感谢分享。
技术流啊
[quote=“abcdcBTBT, post:24, topic:471003”]
可以做到tampermonkey里一键
[/quote]
应该可以 今天在travrel 回去改下
插个眼zs
银卡会员恐怖如斯,老东西终于把焚决交出来了
为什么我更新不了自己的主楼了。。。救命
@uscreditcardguide
伟大的AI帮助轮椅进化了,这次只要
点击link,安装,运行就行
完全不需要任何developer skills了,连按f12都能省掉
greasyfork.org
JL Award on AA Calendar Scanner
Scans JL award availability on aa.com
效果演示
Screenshot 2026-01-03 at 9.13.23 PM1207×1326 253 KB
题外话
【引用自 未知】:
【泥潭国】【恰饭】想要一个泥潭国惊为天人的餐厅合集 旅行
泥潭国作为本坛御用度假国,坛里攻略和游记也不少。
但作为一个出去玩满脑子只有逛到哪吃到哪吃的P人,这里想要一个单纯的惊为天人的日本餐厅合集。
现在的想法是大家能不能每人推荐 一个and only one 在霓虹吃到的最最惊艳的餐厅,不限地点餐种和价格。但是希望大家最好能以好吃程度来推荐,而不是提供的情绪价值。
但确实众口难调,这里说推荐一个是想保证质量。至于要不要去试试就大家各有所好了。我…
希望抢到票的小伙伴们去了霓虹后留下你最珍贵的回忆,作为一个废物死宅吃货我想吃到泥潭所有的好吃的
下次去泥潭国,如果去的城市有你推荐的餐厅,一天能吃六顿的我大概率会去试试
太赞了,想问下这里默认是扫描整个月是吗
【引用自 xjiakskd】:
里默认是扫描整个月是吗
对,calendar api好像只能扫整个月。没有加单独扫天是应为这可能会导致request数量暴涨而被快速block掉。如果需要每天的api看flight details需要搭配ip pool,但那就有成本了并且需要一定的技术能力了。但只scan 特定的单天其实也可以(但我有点懒。。。)
日期的 01 能改成today+1吗,否则不能搜当月的。
【引用自 AnonAno】:
01
感谢指出。但我现在好像改不了主楼了不知道为啥
感谢,好用。
感谢楼主喂饭。
感谢楼主。想问一下楼主我下载了插件但是脚本没有自动弹出来,是被block掉了吗
图像2-10-26 下午4.291920×1243 278 KB
AA/JL 小白,所以,一张票都没有,2月到5月?
这这这!这才是我来这个论坛的真谛!!!!!!(当然还有那个xx区,我不说是哪个)
正在学习如何出里程票,感谢楼主
【引用自 AnonAno】:
伟大的AI帮助轮椅进化了,这次只要
你用的是gemina吗,目前都不用古法编程了
我搜索12个月只找到一张TYO-DFW的票,还要转温哥华,退了退了
此话怎讲?
【引用自 AnonAno】:
现在搜票api不能单独发了,需要cookie和credentials,我们直接从chrome里偷来发api reqest
相当于用的当前session的cookie?但我不登录仍然可以搜票啊 那这样的话意思是只要构造出一个cookie就能匿名发这个请求了?
同, 不知道ui为什么不能自动打开了
感谢楼主 楼主好人!! 差评AA为什么那么多幽灵票。。。
自动化之后确实好用。再请问大佬一下,能不能加个人数选择?或者从code哪里可以改一下?
太牛了,小白问下mac是一样的使用方法吗
一样的 Chrome fn+f12开console
我刚才扫了差不多10个round也被block了,换了个ip还是 block 但是新开浏览器环境要重新验证码登陆 有点麻烦就是
大概 40个calendar request in 10mins
(看起来只ban浏览器环境?)
登陆别的号同ip还是可以搜索
扫到几个,兴奋的点进去定,结果不是尸体就是幽灵票,求大佬指点破解的办法?
不用登录就能扫,就是买票的时候要登录不知道会不会被抢走就是了..
提供几个进阶思路,可以看自己时间和自己能力(其实是calude的能力bushi)慢慢往上加:
加个telegram/discord key,搜到票给自己的一个channel发消息
改成全自动,每隔一段时间扫一下
不要用网页了,用shell script/ python去模拟浏览器
加个ip pool这样可以频繁扫
想问一下楼主怎么做ip pool啊?试着搞了一个,结果被gpt搞的是个假票。让他帮我做ip pool也不肯
IP是不会ban的,只ban浏览器profile。shell script和python没法过Akamai的challenge,必须是自动化浏览器
全自动太容易封了,基本上跑一天就挂了,我自己写了个很复杂的,现在直接跳challenge,还在琢磨怎么破