You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用file_get_contents获取m3u8文件?403错误排查

解决PHP请求m3u8时的403 Forbidden错误

问题场景

我编写了一段PHP代码,分三步发送GET请求获取m3u8文件内容:

  1. 获取有效的token
  2. 携带token拉取主m3u8的链接
  3. 通过拿到的链接获取最终m3u8内容

前两步都正常,但第三步请求返回了403 Forbidden错误。不过通过浏览器审查元素能正常获取到m3u8内容,PHP执行就失败了。

我的PHP代码

<?php 
//1. 创建有效的token以获取m3u8
$opts = array( 
'http'=>array( 
'method'=>"GET", 
'header'=>"Referer: http://www.hotstar.com", 
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:51.0) Gecko/20100101 Firefox/51.0" 
)); 
$context = stream_context_create($opts); 
$url = "http://www.hotstar.com/get_cdn_token.php"; 
$data = file_get_contents($url, false, $context); 
$values = json_decode($data, true); 
$url = $values['token']; 
//2. 携带token发送GET请求拉取主m3u8
$opts = array( 
'http'=>array( 
'method'=>"GET", 
'header'=>"Referer: http://www.hotstar.com", 
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:51.0) Gecko/20100101 Firefox/51.0" 
)); 
$context = stream_context_create($opts); 
$url = "https://secure-getcdn.hotstar.com/AVS/besc?hotstarauth=$url&amp;action=GetCDN&amp;appVersion=5.0.40&amp;asJson=Y&amp;channel=TABLET&amp;id=1000055355&amp;type=VOD"; 
$data = file_get_contents($url, false, $context); 
$values = json_decode($data, true); 
$link = $values['resultObj']['src']; 
//3. 获取m3u8内容
$opts = array( 
'http'=>array( 
'method'=>"GET", 
'header'=>"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:51.0) Gecko/20100101 Firefox/51.0" 
)); 
$context = stream_context_create($opts); 
$url = "$link"; 
$data = file_get_contents($url, false, $context); 
echo $data; 
?>

浏览器中正常获取的m3u8内容

#EXTM3U 
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=241000,RESOLUTION=320x180,CODECS="avc1.66.30, mp4a.40.2",CLOSED-CAPTIONS=NONE 
https://staragvod1-vh.akamaihd.net/i/videos/plus/sns/1365/1000055355_,16,180,400,800,1300,2000,3000,4500,_STAR.mp4.csmil/index_1_av.m3u8?null=0&amp;id=AgC0lfI2aGb2DFFZW1pBPartIAq++S+ee++3UM8jU49rfzGeMpTl2IaWB4PCyZ0c2yGZOtSqAhal4g%3d%3d 
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=461000,RESOLUTION=416x234,CODECS="avc1.66.30, mp4a.40.2",CLOSED-CAPTIONS=NONE 
https://staragvod1-vh.akamaihd.net/i/videos/plus/sns/1365/1000055355_,16,180,400,800,1300,2000,3000,4500,_STAR.mp4.csmil/index_2_av.m3u8?null=0&amp;id=AgC0lfI2aGb2DFFZW1pBPartIAq++S+ee++3UM8jU49rfzGeMpTl2IaWB4PCyZ0c2yGZOtSqAhal4g%3d%3d 
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=861000,RESOLUTION=640x360,CODECS="avc1.66.30, mp4a.40.2",CLOSED-CAPTIONS=NONE 
https://staragvod1-vh.akamaihd.net/i/videos/plus/sns/1365/1000055355_,16,180,400,800,1300,2000,3000,4500,_STAR.mp4.csmil/index_3_av.m3u8?null=0&amp;id=AgC0lfI2aGb2DFFZW1pBPartIAq++S+ee++3UM8jU49rfzGeMpTl2IaWB4PCyZ0c2yGZOtSqAhal4g%3d%3d 
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1360000,RESOLUTION=720x404,CODECS="avc1.66.30, mp4a.40.2",CLOSED-CAPTIONS=NONE 
https://staragvod1-vh.akamaihd.net/i/videos/plus/sns/1365/1000055355_,16,180,400,800,1300,2000,3000,4500,_STAR.mp4.csmil/index_4_av.m3u8?null=0&amp;id=AgC0lfI2aGb2DFFZW1pBPartIAq++S+ee++3UM8jU49rfzGeMpTl2IaWB4PCyZ0c2yGZOtSqAhal4g%3d%3d 
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2060000,RESOLUTION=1280x720,CODECS="avc1.77.30, mp4a.40.2",CLOSED-CAPTIONS=NONE 
https://staragvod1-vh.akamaihd.net/i/videos/plus/sns/1365/1000055355_,16,180,400,800,1300,2000,3000,4500,_STAR.mp4.csmil/index_5_av.m3u8?null=0&amp;id=AgC0lfI2aGb2DFFZW1pBPartIAq++S+ee++3UM8jU49rfzGeMpTl2IaWB4PCyZ0c2yGZOtSqAhal4g%3d%3d 
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=3060000,RESOLUTION=1600x900,CODECS="avc1.77.30, mp4a.40.2",CLOSED-CAPTIONS=NONE 
https://staragvod1-vh.akamaihd.net/i/videos/plus/sns/1365/1000055355_,16,180,400,800,1300,2000,3000,4500,_STAR.mp4.csmil/index_6_av.m3u8?null=0&amp;id=AgC0lfI2aGb2DFFZW1pBPartIAq++S+ee++3UM8jU49rfzGeMpTl2IaWB4PCyZ0c2yGZOtSqAhal4g%3d%3d 
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=4562000,RESOLUTION=1920x1080,CODECS="avc1.77.30, mp4a.40.2",CLOSED-CAPTIONS=NONE 
https://staragvod1-vh.akamaihd.net/i/videos/plus/sns/1365/1000055355_,16,180,400,800,1300,2000,3000,4500,_STAR.mp4.csmil/index_7_av.m3u8?null=0&amp;id=AgC0lfI2aGb2DFFZW1pBPartIAq++S+ee++3UM8jU49rfzGeMpTl2IaWB4PCyZ0c2yGZOtSqAhal4g%3d%3d

PHP执行时的错误信息

Warning: file_get_contents(https://staragvod1-vh.akamaihd.net/i/videos/plus/sns/1365/1000055355_,16,180,400,800,1300,2000,3000,4500,_STAR.mp4.csmil/master.m3u8?hdnea=st=1515937603~exp=1515938203~acl=/*~hmac=c5f9294a198233a9751edbca51631c9cb12db63a08a69499c20d1208bd07aca8): failed to open stream: HTTP request failed! HTTP/1.0 403 Forbidden in **** on line 37

解决方案

核心原因

403 Forbidden错误通常是因为服务器验证请求的合法性失败——你的PHP请求头和浏览器的请求头不一致,服务器识别出这不是来自合法浏览器的请求,所以拒绝了。

看你的代码,第三步请求只带了User-Agent,但缺少了前两步都有的Referer头,这很可能是关键原因。另外,浏览器发送的请求头还包含Accept、Accept-Language等字段,这些也可能是服务器验证的一部分。

修改步骤

  1. 添加Referer头:给第三个请求加上和前两步一样的Referer: http://www.hotstar.com,这是最关键的一步。
  2. 补全其他请求头:复制浏览器中请求m3u8时的完整请求头(可以通过开发者工具的Network标签查看),确保PHP请求和浏览器请求的头信息完全一致。
  3. 必要时添加Cookie:如果浏览器请求中带有Cookie,也要把Cookie字段加到PHP的请求头里。

修改后的第三步代码示例

//3. 获取m3u8内容
$opts = array( 
    'http'=>array( 
        'method'=>"GET", 
        'header'=>"Referer: http://www.hotstar.com\r\n" .
                  "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:51.0) Gecko/20100101 Firefox/51.0\r\n" .
                  "Accept: */*\r\n" .
                  "Accept-Language: en-US,en;q=0.5\r\n" .
                  "Accept-Encoding: gzip, deflate, br\r\n" .
                  "Connection: keep-alive"
    ),
    // 如果HTTPS验证有问题,可以临时添加这个(不建议长期使用,最好配置正确的CA证书)
    'ssl' => array(
        'verify_peer' => false,
        'verify_peer_name' => false,
    )
); 
$context = stream_context_create($opts); 
$url = $link; 
$data = file_get_contents($url, false, $context); 
echo $data; 

额外提示

  • 如果你不确定浏览器的请求头,可以打开开发者工具(F12),在Network标签中找到获取m3u8的请求,查看Request Headers部分,把所有字段都复制到PHP的header数组中。
  • 某些CDN(比如Akamai)会验证请求的签名和来源,确保请求头和签名是匹配的,所以保持请求头和浏览器一致是关键。

内容的提问来源于stack exchange,提问作者waylan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:51:32