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

使用Java RestTemplate调用FlightRadar24 API遭Cloudflare 403拦截求助

问题

我尝试用Java + Spring RestTemplate调用FlightRadar24 API获取航班数据,却收到Cloudflare返回的403 Forbidden错误。

需求说明

根据FlightRadar24 API文档,请求需满足:

  • 基础URL:https://fr24api.flightradar24.com/api
  • Authorization头部携带Bearer格式的API令牌
  • Accept-Version头部设置为v1
  • 发送GET请求到对应端点

我的代码

package ch.ais.www.services;

import java.util.Collections;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;

public class Fr24Service {
    private final RestTemplate restTemplate = new RestTemplate();
    private final String apiToken = "your_api_token_here";
    private final String baseUrl = "https://fr24api.flightradar24.com/api";

    public String getFlightData(String flightId) {
        String url = String.format("%s/flights/%s", baseUrl, flightId);

        // Set headers
        HttpHeaders headers = new HttpHeaders();
        headers.setBearerAuth(apiToken); // Set Authorization header
        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
        headers.add("Accept-Version", "v1");
        headers.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");

        // Create request entity
        HttpEntity<String> entity = new HttpEntity<>(headers);

        // Send GET request
        ResponseEntity<String> response;
        try {
            response = restTemplate.exchange(
                url, HttpMethod.GET, entity, String.class);
        } catch (HttpClientErrorException e) {
            // Handle HTTP errors
            System.err.println("HTTP Status Code: " + e.getStatusCode());
            System.err.println("Response Body: " + e.getResponseBodyAsString());
            throw e;
        }

        if (response.getStatusCode() == HttpStatus.OK) {
            return response.getBody();
        } else {
            // Error handling
            throw new RuntimeException("Error fetching flight data: " + response.getStatusCode());
        }
    }
}

遇到的错误

运行时抛出异常:

Exception in thread "main" org.springframework.web.client.HttpClientErrorException$Forbidden: 403 Forbidden: "<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en-US"> <![endif]-->
<!--[if IE 7]>    <html class="no-js ie7 oldie" lang="en-US"> <![endif]-->
<!--[if IE 8]>    <html class="no-js ie8 oldie" lang="en-US"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en-US"> <!--<![endif]-->
<head>
<title>Attention Required! | Cloudflare</title>
...

Cloudflare拦截了请求,返回HTML验证页面而非预期的JSON响应。

补充信息

使用Java 21 + Spring RestTemplate,Cloudflare将请求识别为自动化流量拦截。API凭证合法,已按文档要求设置必要头部。

已尝试方案

  • 验证apiToken正确有效
  • 确认Authorization头部为Bearer格式
  • 设置Accept-Version为v1
  • 添加模拟浏览器的User-Agent头部
  • Postman和curl测试请求可正常返回数据
  • 确认端点URL无误
  • 尝试Spring WebFlux WebClient,仍出现相同403错误
  • 启用日志检查请求和响应细节

核心问题

在拥有合法API凭证的情况下,如何配置RestTemplate或其他HTTP客户端,绕过Cloudflare拦截成功请求FlightRadar24 API?


解决方案

1. 完全复刻Postman/curl的请求头

Cloudflare会通过请求头完整性判断是否为自动化流量,Postman能成功则说明它的请求头被认可。打开Postman的「请求详情」,复制所有请求头(包括Accept-Language、Referer、Accept-Encoding等),全部添加到RestTemplate的请求中:

headers.add("Accept-Language", "en-US,en;q=0.9");
headers.add("Referer", "https://www.flightradar24.com/");
headers.add("Accept-Encoding", "gzip, deflate, br");
headers.add("Connection", "keep-alive");

不要遗漏任何Postman发送的头部,尤其是看似无关的字段。

2. 配置RestTemplate支持Cookie管理

Cloudflare可能通过Cookie验证会话,默认RestTemplate的HttpClient未启用Cookie持久化。自定义RestTemplate配置,启用CookieStore:

@Bean
public RestTemplate fr24RestTemplate() {
    CloseableHttpClient httpClient = HttpClientBuilder.create()
            .setDefaultCookieStore(new BasicCookieStore())
            .build();
    HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
    return new RestTemplate(factory);
}

使用这个自定义的RestTemplate,确保会话Cookie能被保存和复用。

3. 预请求获取Cloudflare验证Cookie

如果直接请求被拦截,可以先发送不带Authorization的请求到API端点,获取Cloudflare返回的验证Cookie,再携带Cookie和API凭证发送实际请求:

// 第一步:获取Cloudflare会话Cookie
HttpHeaders preHeaders = new HttpHeaders();
preHeaders.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
HttpEntity<String> preEntity = new HttpEntity<>(preHeaders);
ResponseEntity<String> preResponse = restTemplate.exchange("https://fr24api.flightradar24.com/api", HttpMethod.GET, preEntity, String.class);

// 提取Cookie
Set<String> cookies = preResponse.getHeaders().get(HttpHeaders.SET_COOKIE);

// 第二步:携带Cookie和API凭证发送请求
HttpHeaders flightHeaders = new HttpHeaders();
flightHeaders.setBearerAuth(apiToken);
flightHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
flightHeaders.add("Accept-Version", "v1");
flightHeaders.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
if (cookies != null) {
    flightHeaders.put(HttpHeaders.COOKIE, cookies);
}
// 添加其他复刻的请求头...
HttpEntity<String> flightEntity = new HttpEntity<>(flightHeaders);
ResponseEntity<String> flightResponse = restTemplate.exchange(url, HttpMethod.GET, flightEntity, String.class);

4. 使用更贴近浏览器的HTTP客户端(如OkHttp)

RestTemplate默认的HttpClient配置不够贴近浏览器行为,换成OkHttp客户端:
先添加OkHttp依赖:

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.12.0</version>
</dependency>

再配置RestTemplate使用OkHttp:

@Bean
public RestTemplate okHttpRestTemplate() {
    OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .cookieJar(new CookieJar() {
                private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
                @Override
                public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                    cookieStore.put(url.host(), cookies);
                }
                @Override
                public List<Cookie> loadForRequest(HttpUrl url) {
                    List<Cookie> cookies = cookieStore.get(url.host());
                    return cookies != null ? cookies : Collections.emptyList();
                }
            })
            .build();
    OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory(okHttpClient);
    return new RestTemplate(factory);
}

配合完整的请求头,更容易通过Cloudflare检测。

5. 控制请求频率

Cloudflare会拦截短时间内的高频请求,确保请求频率符合FlightRadar24 API的限制,批量请求时添加适当延迟。


内容的提问来源于stack exchange,提问作者Ivan Leo Otero Mora

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 20:56:04