TUTORIAL

How to Get Football Data with Java - Complete API Tutorial

Step-by-step Java tutorial for fetching football fixtures, match stats and odds via API using HttpClient and Jackson. Working code examples you can copy.

4 min read

Java powers a lot of backend services, Android data layers, and Spring Boot APIs. TheStatsAPI is a plain REST JSON API, so you can use the built-in java.net.http.HttpClient (Java 11+) and Jackson for parsing - no SDK required.

This tutorial shows how to fetch football data with Java: competitions, fixtures, pagination, match stats, and odds.

Prerequisites

You need:

  • Java 11+ (for java.net.http.HttpClient)
  • Jackson for JSON parsing
  • A TheStatsAPI API key

Add Jackson with Maven:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.17.1</version>
</dependency>

Set your API key as an environment variable:

export THESTATSAPI_KEY="your_api_key"

If you do not have a key yet, sign up at thestatsapi.com for a 7-day free trial.

Create a Small API Client

Create FootballApi.java. It returns a parsed Jackson JsonNode so every example can read fields directly.

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.stream.Collectors;

public class FootballApi {
    private static final String BASE_URL = "https://api.thestatsapi.com/api";
    private static final String API_KEY = System.getenv("THESTATSAPI_KEY");
    private static final HttpClient CLIENT = HttpClient.newHttpClient();
    private static final ObjectMapper MAPPER = new ObjectMapper();

    public static JsonNode get(String endpoint, Map<String, String> params) throws Exception {
        String query = params.entrySet().stream()
                .map(e -> URLEncoder.encode(e.getKey(), StandardCharsets.UTF_8)
                        + "=" + URLEncoder.encode(e.getValue(), StandardCharsets.UTF_8))
                .collect(Collectors.joining("&"));

        String url = BASE_URL + endpoint + (query.isEmpty() ? "" : "?" + query);

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Authorization", "Bearer " + API_KEY)
                .header("Accept", "application/json")
                .GET()
                .build();

        HttpResponse<String> response = CLIENT.send(request, HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() >= 400) {
            throw new RuntimeException("API request failed: HTTP " + response.statusCode());
        }

        return MAPPER.readTree(response.body());
    }

    public static JsonNode get(String endpoint) throws Exception {
        return get(endpoint, Map.of());
    }
}

URLEncoder keeps query parameters safe. Every example below reuses FootballApi.get().

Fetch Competitions

import com.fasterxml.jackson.databind.JsonNode;
import java.util.Map;

public class Competitions {
    public static void main(String[] args) throws Exception {
        JsonNode result = FootballApi.get("/football/competitions",
                Map.of("search", "Premier League"));

        for (JsonNode competition : result.get("data")) {
            System.out.println(competition.get("id").asText() + " "
                    + competition.get("name").asText() + " "
                    + competition.get("country").asText());
        }
    }
}

Typical output:

comp_3039 Premier League England

Save the competition ID for match and season queries.

Get Fixtures for a League

import com.fasterxml.jackson.databind.JsonNode;
import java.util.Map;

JsonNode result = FootballApi.get("/football/matches", Map.of(
        "competition_id", "comp_3039",
        "per_page", "10"
));

for (JsonNode match : result.get("data")) {
    String home = match.get("home_team").get("name").asText();
    String away = match.get("away_team").get("name").asText();
    String status = match.get("status").asText();
    String date = match.get("utc_date").asText();
    System.out.printf("%s - %s vs %s (%s)%n", date, home, away, status);
}

Add date_from, date_to, season_id, team_id, and status to filter. See the fixtures API.

Handle Pagination

List endpoints return a meta block with total_pages.

import com.fasterxml.jackson.databind.JsonNode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public static List<JsonNode> getAll(String endpoint, Map<String, String> baseParams) throws Exception {
    List<JsonNode> rows = new ArrayList<>();
    int page = 1;

    while (true) {
        Map<String, String> params = new HashMap<>(baseParams);
        params.put("page", String.valueOf(page));

        JsonNode result = FootballApi.get(endpoint, params);
        result.get("data").forEach(rows::add);

        int totalPages = result.path("meta").path("total_pages").asInt(1);
        if (page >= totalPages) break;
        page++;
    }

    return rows;
}

Run backfills like this in a scheduled job and cache the rows in your database.

Get Match Stats

import com.fasterxml.jackson.databind.JsonNode;

JsonNode data = FootballApi.get("/football/matches/mt_010249745/stats").get("data");
JsonNode overview = data.get("overview");

JsonNode xg = overview.get("expected_goals").get("all");
JsonNode shots = overview.get("total_shots").get("all");

System.out.println("Shots: " + shots.get("home").asText() + " - " + shots.get("away").asText());
System.out.println("xG: " + xg.get("home").asDouble() + " - " + xg.get("away").asDouble());

See the match stats API and xG API.

Get Pre-Match Odds

import com.fasterxml.jackson.databind.JsonNode;

JsonNode data = FootballApi.get("/football/matches/mt_010249745/odds").get("data");

for (JsonNode book : data.get("bookmakers")) {
    JsonNode matchOdds = book.path("markets").path("match_odds");
    if (matchOdds.isMissingNode()) continue;
    System.out.println(book.get("bookmaker").asText() + ": " + matchOdds);
}

Use /football/matches/{match_id}/odds/live for in-play odds. See the Football Odds API.

Production Tips

  • Keep the API key in environment variables or a secrets manager.
  • Reuse a single HttpClient instance - it is thread-safe and pools connections.
  • Cache responses to respect plan limits.
  • Use pagination for backfills and run them outside request threads.
  • Check availability flags such as xg_available and live_odds_available.

FAQ

Can I use Java with TheStatsAPI?

Yes. TheStatsAPI is a REST JSON API, so Java's built-in HttpClient (Java 11+) works directly. The examples above parse responses with Jackson.

Do I need a Java SDK?

No. Plain HTTP requests with HttpClient and a JSON library like Jackson or Gson are enough, and they work in plain Java, Spring Boot, and Android.

How do I fetch football odds in Java?

Use /football/matches/{match_id}/odds for pre-match odds and /football/matches/{match_id}/odds/live for live odds where available.

How do I get xG data in Java?

Call /football/matches/{match_id}/stats and read overview.expected_goals.all for team xG.

Start building today

Ready to Power Your Sports App?

Start your 7-day free trial. All endpoints included on every plan.

Cancel anytime
7-day free trial
Setup in 5 minutes