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

使用URLSession获取网页返回403,如何模拟curl请求?

curl与URLSession GET请求的核心区别
  • 默认请求头差异:curl会自动填充多个默认请求头(如Accept-Encoding、Connection),而URLSession仅添加少量必要头,缺失这些细节可能触发网站的反爬虫校验。
  • Cookie处理逻辑:curl默认复用本地Cookie文件中的存储内容,而URLSession使用独立的Cookie容器,若网站依赖Cookie验证请求合法性,会导致请求失败。
  • SSL/TLS实现细节:curl基于OpenSSL库,URLSession使用Apple原生的Security.framework,部分网站会校验SSL指纹或TLS协议版本,两者的默认配置可能不匹配。
  • 连接复用策略:curl和URLSession的HTTP连接池复用逻辑不同,部分网站会通过连接特征识别爬虫请求。
用URLSession模拟curl请求的步骤
  1. 完整复制curl的请求头
    执行curl --verbose https://your-target-url.com,复制所有发送的请求头(包括Accept-Encoding、Connection等curl自动添加的头),将它们全部添加到URLRequest中,不要遗漏任何一项。

  2. 同步Cookie(若需要)
    如果curl请求中包含Cookie头(从--verbose输出中查看),将对应Cookie值直接添加到请求:

    urlRequest.setValue("cookie-key1=value1; cookie-key2=value2", forHTTPHeaderField: "Cookie")
    

    或者配置URLSession的全局Cookie容器:

    let configuration = URLSessionConfiguration.default
    if let cookie = HTTPCookie(properties: [
        .name: "cookie-name",
        .value: "cookie-value",
        .domain: "websiteurl.com",
        .path: "/"
    ]) {
        HTTPCookieStorage.shared.setCookie(cookie)
    }
    let session = URLSession(configuration: configuration)
    
  3. 匹配SSL/TLS配置
    若网站对TLS版本有要求,可调整URLSession的TLS配置:

    let configuration = URLSessionConfiguration.default
    configuration.tlsMinimumSupportedProtocolVersion = .TLSv12
    let session = URLSession(configuration: configuration)
    
  4. 校验请求一致性
    用抓包工具(如Charles)对比curl和URLSession的请求包,确保请求行、所有头字段、连接参数完全一致。

针对你的代码的修改建议

你当前只添加了3个请求头,缺少curl默认的Accept-Encoding、Connection等关键头,修改后的代码示例:

guard let url = URL(string: "https://websiteurl.com") else {
    fatalError("无效URL")
}

var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "GET"

// 从curl --verbose获取的完整请求头
urlRequest.setValue("websiteurl.com", forHTTPHeaderField: "Host")
urlRequest.setValue("curl/8.4.0", forHTTPHeaderField: "User-Agent")
urlRequest.setValue("*/*", forHTTPHeaderField: "Accept")
urlRequest.setValue("gzip, deflate, br", forHTTPHeaderField: "Accept-Encoding")
urlRequest.setValue("keep-alive", forHTTPHeaderField: "Connection")
// 若curl输出中有其他头(如Upgrade-Insecure-Requests)也需添加
urlRequest.setValue("1", forHTTPHeaderField: "Upgrade-Insecure-Requests")

do {
    let (data, response) = try await URLSession.shared.data(for: urlRequest)
    if let httpResponse = response as? HTTPURLResponse {
        print(httpResponse.statusCode)
        // 可打印响应体查看反爬虫提示
        if let responseBody = String(data: data, encoding: .utf8) {
            print(responseBody)
        }
    }
} catch {
    print("请求错误: \(error)")
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 03:20:15