如何拦截TikTok移动API请求触发的验证码并完成验证以恢复接口访问
如何拦截TikTok移动API请求触发的验证码并完成验证以恢复接口访问
我在爬取TikTok Shop的时候,因为它仅支持移动端访问,所以尝试调用它的移动API接口,但当发送请求过于频繁时,API会返回如下错误:
{ "code": -9999, "message": "internal error" }
出现这个错误后,我在手机端打开TikTok时会看到验证码验证界面,只有完成验证码验证后,API请求才能恢复正常。

我观察到验证码的处理流程是这样的:首先会发送一个GET请求到验证码相关地址,接着发送两次GET请求获取验证码图片;验证成功后,会向验证码地址发送一个POST请求,携带一些混淆后的参数。
经过大量测试后我发现,TikTok Shop的商品信息查询API端点仅需要我使用的模拟器的设备ID就能正常工作,这是经过各种Header测试后确认的唯一必填项。现在我需要能通过设备ID来复刻请求,以下是我当前发送请求的代码:
# TikTok Shop商品信息查询API地址 url = "oec19-normal-useast5.tiktokv.us/api/v1/shop/product_info/get" # 请求参数 params = { "device_platform": "android", # 标识设备平台(Android) "os": "android", # 指定操作系统类型 "ssmix": "a", # 应用特定配置参数 "_rticket": "1735656534122", # 请求时间戳 "cdid": "97fad962-8535214354240a836c9555", # 客户端唯一设备ID "channel": "googleplay", # 应用分发渠道(Google Play商店) "aid": "1233", # TikTok内部应用ID "app_name": "musical_ly", # 应用名称标识 "version_code": "370903", # 应用版本代码 "version_name": "37.9.3", # 应用版本名称 "manifest_version_code": "48828923", # 应用内部清单版本代码 "update_version_code": "2022049030", # 应用更新版本代码 "ab_version": "37.9.3", # A/B测试版本标识 "resolution": "1600*900", # 设备屏幕分辨率 "dpi": "320", # 设备屏幕密度 "device_type": "SM-G998N", # 设备型号(三星Galaxy S20 Ultra) "device_brand": "samsung", # 设备品牌 "language": "en", # 用户语言设置 "os_api": "22", # Android系统API级别(对应7.1.2版本) "os_version": "7", # 操作系统版本 "ac": "wifi", # 当前网络类型 "is_pad": "0", # 是否为平板设备 "current_region": "US", # 用户当前所在地区 "app_type": "normal", # 应用类型(普通版) "sys_region": "FR", # 系统地区设置 "last_install_time": "1732924273", # 应用最后安装时间戳 "mcc_mnc": "322456", # 移动国家/网络代码 "timezone_name": "Africa/Brazzaville", # 时区名称 "carrier_region_v2": "300", # 运营商地区标识 "residence": "US", # 用户常驻地区 "build_number": "36", # 应用构建版本号 "uoo": "0", # 应用特定配置参数 "carrier_region": "US", # 运营商地区 "region": "GB", # 用户地区标识 "locale": "en-GB", # 区域语言设置 "op_region": "US", # 服务运营地区 "content_language": "en,ru,", # 偏好内容语言 "timezone_offset": "3600", # 时区偏移(秒) "ts": "1735654933", # 请求时间戳 "app_language": "en", # 应用内语言设置 "ac2": "wifi", # 备用网络类型 "host_abi": "arabi-v7a", # 设备CPU架构 "iid": "3435643", # 应用安装唯一ID "device_id": "42424492482942", # 核心设备唯一ID(模拟器设备ID) "openudid": "39448Dd", # 开放设备唯一ID } # 请求头信息 second_headers = { "Accept-Encoding": "gzip", "Connection": "Keep-Alive", "Content-Length": "1785", "Content-Type": "application/json; charset=UTF-8", "Host": "oec19-normal-useast5.tiktokv.us", "oec-vc-sdk-version": "3.0.5.i18n", "passport-sdk-version": "6033840", "rpc-persist-pyxis-policy-v-tnc": "1", "sdk-version": "2", "User-Agent": "com.zhiliaoapp.musically/2023709030 (Linux; U; Android 7.1.2; en_GB; SM-G988N; Build/NRD90M;tt-ok/3.12.13.16)", "X-Argus": "o+HE69eMgMQi0mtZTKUey6LXbWNId2zPIoTaWuPSQTfU4kXQD+m/5wjIB4KlyqGeLTYZpaqC4Z4hWArBznJ9TEWlAFv8gYMOzVvp/bQmLiKXobtMgfUqo8j3D0Ls3a/oTjhSIzd/JISpmf4ZFXYbR5QHk7mRqxJhedbT00suLyLDUHqIH0sIph7IovnI603LHJ1oDjSPnK51txrWYCTEH3J04d7z8WavsFOH+TdJflHIPLB8F0lmTwookUrV7tlNcJ80mcY8o7Jc83kmkwixhr6XJ77XCNk8eLELUV4VKXfZZteEJPo2XoQ9LG8zRkGF1zy4KG4Cf4bFQVGVcGng8yUhJ/wpJBahw2hR/QEI8AuchtPEwCuMFo7eID46mGMLuLCIiobxMfq+d6HiY1cUZXV6OfI5lJz7L5zB8In2WXDMIfDj5kCC0vLO77/7NEgOStoZAk7DQgekYNnUCRGHfbPI7Z/hW/tEXPofRg6sV1YTNY5KOxVlDG4wgUDP4Y8XKR+vRMtJ/yQnOj3S7JvzJbYFFJZoG8yrrzcXFfWga7wCJCozzPQDq6JWiu6bZ1Y7oFq9xey55eeqbw4U/VX0xUMOKqptdUYnKbVB0cXuDySKQ=", "x-bd-client-key": "#gL3JJ3JDNXS2Pc4QLPLvtNfliviDO+MNs07QbaVrHBg8iVVN", "x-bd-kmsv": "0", "X-Gorgon": "0404401040010bdd2fe8d7c93a42c35223a65", "X-Khronos": "4442484", "X-Ladon": "M/oMR2344QLz95ntHX74Vm8glLwbVpf", "X-SS-REQ-TICKET": "17356575TY3", "X-SS-STUB": "14772E37DDDZSCD33253535D58A2E3564", "x-tt-dm-status": "login=0;ct=0;rt=0", "x-tt-pba-enable": "1", "x-tt-request-tag": "n=0;nr=011;bg=0", "x-tt-store-region": "us", "x-tt-store-region-src": "us", "X-Tt-Token": "0408b4f30f13360e7c6c08c81a29ecaba232fbdeeefeif33djDNJDdcdc18f657390484e1387bb6dc036620b92fe47f7052bfbc6ef0769ddca35075b6793ae7-CkBkMDdhM2Q4M2VkNWI5NGYxYzllODc3M2NmOTQxZjU4Mzk4NGRjMWUyZWZhYjM4NzRmNWE4YjI0ZWViMDg5NWU0-2.0.0", "x-vc-bdturing-sdk-version": "2.3.8.i18n" } # 请求体数据 second_case = { "request_scene": 1, "product_id": [ "1729601859019968807" ], "should_use_ocp": 0, "page_source_info": "{\"ec_head\":{\"extra\":{\"ec_is_video_page\":\"0\"},\"page_name\":\"b2001\"},\"page_source_list\":[{\"extra\":{\"ec_is_video_page\":\"0\"},\"page_name\":\"b2001\"},{\"extra\":{\"traffic_diversion_info\":\"{\\\"traffic_out_source\\\":\\\"homepage_top_2tab.in_app\\\",\\\"traffic_material_id\\\":\\\"\\\",\\\"traffic_campaign_id\\\":\\\"\\\",\\\"traffic_track_id\\\":\\\"1735656518216\\\",\\\"mall_btm\\\":\\\"a2270.b0865.c8938.d9932_i18\\\",\\\"mall_bcm\\\":\\\"|||\\\"}\",\"feed_tab\":\"0|0\",\"prefix_ec_params_origin_is_mall_tab\":\"homepage_mall\",\"bcm_feed_tab\":\"0\",\"bcm_nova_delivery_id\":\"nd202412311505067277000000000000104609958221062\",\"ec_next_page_c_btm_code\":\"c8938\",\"ec_next_page_d_btm_code\":\"d9932_i18\"},\"page_name\":\"b0865\"},{\"page_name\":\"b6661\"}]}", "biz_template": 3, "promotion_response_style": 1, "traffic_signature": "{\"scene\":\"Default.Western_Mall.Homepage_Feeds.Common\"}", "kol_id": "7495541563206240551", "template": "tt_pdp_full", "product_enter_context": { "1729601859019968807": { "req_type": 1, "is_from_selection_scenarios": False } }, "experiment": { "param": { "ecom_logistic_display_opt": 1, "display_history_shipday": 1, "ecom_pdp_folding_display": 1, "is_new_pdp_logistic_module": 1, "is_new_pdp_sales_count_text": 1, "segregate_review_list": 1, "pdp_promo_cx_optimization": 0, "pdp_desc_layout_improve": 1 }, "params_map": { "logistic_move_up_config": "{}", "pdp_first_screen_opt_config": "{\"full_pdp_header_to_top\":false,\"has_label_floor\":false,\"promotion_and_waist_up\":false,\"half_pdp_shorten_height\":false,\"base_ui_change\":false}" } }, "preselect_spec_ids": [], "traffic_source_list": [ 6 ], "product_source_info": { "1729601859019968807": 6 }, "ship_to_addr": [] }
我现在的核心需求是:当触发验证码限制后,能够模拟完成验证码验证的流程,让对应的设备ID恢复API访问权限,或者直接通过设备ID复刻出可正常访问的请求。
备注:内容来源于stack exchange,提问作者Kirada




