Do referees favour the home side?
Away players are booked more often per foul than home players, in every one of 26 Scottish seasons. Much of that is because away sides do more defending. Compare like with like and a gap of 10 to 20% remains, and it all but vanished in the season without crowds.
Intermediate
Contents
The research question
Every away end has sung it: the referee's a homer. Do referees really treat home sides more kindly? And if away players are booked more, is that the referee, or is it how away teams play?
It's a question with a trap built in, the kind covered in do football stats mislead?: a hidden cause that could produce the pattern on its own.
The dataset
Every Scottish Premiership match from 2000/01 to 2025/26 in the football-data.co.uk files with shots, fouls and cards recorded: 5,877 matches, of which 5,649 name the referee, 152 referees in all.
The method
- Cards per foul, not cards per game. A side that commits more fouls will get more cards with a perfectly fair referee, so the fair measure is how often a foul is punished with a yellow card.
- Which side was defending? Away sides are usually outshot, so they do more defending, and fouls made while defending, stopping a break or a cross, are the kind referees book. So the comparison is repeated by which side had more shots.
- Like with like. Compare defending away sides with defending home sides, and attacking with attacking.
- A natural experiment. In 2020/21, every Scottish match was played behind closed doors.
- Referees one by one, counted, not named. Is the gap a few referees or nearly all of them, and do they differ by more than luck?
Every comparison comes with a luck margin, the range that 95% of resamples of the matches fall in.
Results
Away sides are booked more, and not only because they foul more
Per game, home sides committed 12.06 fouls and away sides 12.62, only half a foul more. But away sides picked up 1.85 yellow cards a game against the home side's 1.50, and 0.117 red cards against 0.087.
Per foul: home sides got 0.125 yellow cards for each foul, about one for every eight; away sides 0.147, about one for every seven. Away sides are booked 1.18 times as often per foul (luck margin 1.15 to 1.21), and the gap is there in all 26 seasons.
Most of the gap is about defending
Now split the matches by which side had more shots:
| Matches | Away foul booked, times as often |
|---|---|
| Home side outshot the away side (3,431) | 1.34 |
| Level on shots (346) | 1.13 |
| Away side outshot the home side (2,100) | 0.97 |
When the away side has more of the play, its fouls are booked no more often than the home side's: 0.97, luck margin 0.94 to 1.01. The big gap comes in the matches where the away side is pinned back, and those are the majority. A large part of "referees book away teams more" is really "referees book defending teams more", and away teams defend more.
Like with like, a gap remains
The fair comparison is a defending away side against a defending home side, and an attacking side against an attacking side:
| Comparing | Yellows per foul, away v home | Away, times as often |
|---|---|---|
| Defending | 0.153 v 0.140 | 1.10 (1.06 to 1.14) |
| Attacking | 0.136 v 0.114 | 1.19 (1.14 to 1.24) |
Both luck margins stay clear of 1. Doing the same thing, an away player is booked 10 to 20% more often. Defending is part of the story, but not all of it.
Behind closed doors
If the gap comes from the crowd, it should shrink without one. In 2020/21 every match was played behind closed doors, and the gap fell to 1.03, the lowest of all 26 seasons.
But one season is only 228 matches, and its luck margin runs from 0.90 to 1.18: wide enough to include no gap at all, and only just reaching a normal season. It points the same way as the crowd explanation without proving it, exactly as the 2020/21 test of home advantage found for goals. Larger studies of empty stadiums, in Italy and in Germany's ghost games, found the same direction with more matches (see Further reading).
Nearly every referee, not a few
This piece doesn't name or rank referees, on purpose. Of the 16 referees with 100 or more matches, 15 booked away fouls more often than home fouls. And the differences between them are about what luck alone would produce: hand the same matches out to referees at random and they come out as spread out as the real ones 11% of the time. No referee stands out from the rest by more than chance, so a league table of "the most biased referees" would be measuring luck.
Limitations
- Fouls aren't all alike. A foul that stops a counter-attack is more bookable than one in midfield; defending sides make more of them. Splitting by shots catches much of that, but not all.
- Per foul, not per booked foul. Some yellow cards are for dissent or time-wasting rather than a foul, so yellows per foul is a fair comparison between sides, not a count of how many fouls were booked.
- Cards only. Penalties, free kicks, added time and offside calls might show a home lean too; this data doesn't have them.
- Why, not just whether. The crowd is the likeliest explanation, and the empty-stadium season points that way, but the data can't rule out others, such as away sides' tactics or travel.
- Not a verdict on any referee. The pattern is league-wide; nothing here says any one referee is biased.
Conclusion
Away fans have a point, a smaller one than they think. Much of the extra booking of away teams comes from away teams doing more defending. Compare like with like and away players are still booked 10 to 20% more often per foul, the gap has narrowed over 26 seasons, it was smallest in the season played without crowds, and it's almost every referee, not one or two. The likeliest reason is the thing referees can't switch off: the crowd.
Reproduce the analysis
The results files are published by football-data.co.uk. Download the Premiership file (SC0) for each season from 2000/01 to 2025/26 and save each under its own name, such as SC0_2425.csv; they aren't rehosted on this site. It takes about ten seconds, most of it the resampling:
Show the Python93 lines, ready to copy and run.
import csv
import random
from collections import defaultdict
from math import log, sqrt
from statistics import mean
COLUMNS = ("HS", "AS", "HF", "AF", "HY", "AY", "HR", "AR")
names = [f"{y % 100:02d}{(y + 1) % 100:02d}" for y in range(2000, 2026)]
matches = []
for s in names:
with open(f"SC0_{s}.csv", encoding="latin-1") as f:
for r in csv.DictReader(f):
if all(r.get(c) for c in COLUMNS):
matches.append({"season": s, "referee": (r.get("Referee") or "").strip(), **{c: int(r[c]) for c in COLUMNS}})
rnd = random.Random(2026) # fixed, so the luck margins repeat exactly
def booked_per_foul(group): # yellow cards per foul, home side and away side
hy, ay, hf, af = (sum(m[c] for m in group) for c in ("HY", "AY", "HF", "AF"))
return hy / hf, ay / af
def away_vs_home(group): # how many times more often an away foul is booked than a home foul
home, away = booked_per_foul(group)
return away / home
def luck_margin(stat, *groups, n=1000): # 95% range from resampling the matches
draws = sorted(stat(*([g[rnd.randrange(len(g))] for _ in g] for g in groups)) for _ in range(n))
return draws[int(0.025 * n)], draws[int(0.975 * n)]
print(f"{len(matches)} matches with shots, fouls and cards; {sum(m['referee'] != '' for m in matches)} name the referee")
per_game = {c: mean(m[c] for m in matches) for c in COLUMNS}
print("per game, home v away: fouls {HF:.2f} v {AF:.2f}, yellows {HY:.2f} v {AY:.2f}, reds {HR:.3f} v {AR:.3f}".format(**per_game))
# 1. the raw gap: booked per foul
home, away = booked_per_foul(matches)
lo, hi = luck_margin(away_vs_home, matches)
print(f"booked per foul: home {home:.3f}, away {away:.3f}; away {away / home:.2f} times as often ({lo:.2f} to {hi:.2f})")
by_season = {s: away_vs_home([m for m in matches if m["season"] == s]) for s in names}
print("by season: " + ", ".join(f"20{s[:2]}/{s[2:]} {v:.2f}" for s, v in by_season.items()))
print(f"seasons with the away side booked more often per foul: {sum(v > 1 for v in by_season.values())} of {len(by_season)}")
early = [m for m in matches if m["season"] < "0708"]
late = [m for m in matches if m["season"] >= "1920"]
print(f"first seven seasons {away_vs_home(early):.2f}, last seven {away_vs_home(late):.2f}")
# 2. behind closed doors: 2020/21
empty = [m for m in matches if m["season"] == "2021"]
lo, hi = luck_margin(away_vs_home, empty)
print(f"2020/21, no crowds: {away_vs_home(empty):.2f} ({lo:.2f} to {hi:.2f}), {len(empty)} matches; "
f"lowest season: {min(by_season, key=by_season.get) == '2021'}")
# 3. the confounder: who was defending? (the side with fewer shots)
for label, keep in (("home side outshot the away side", lambda m: m["HS"] > m["AS"]),
("level on shots", lambda m: m["HS"] == m["AS"]),
("away side outshot the home side", lambda m: m["AS"] > m["HS"])):
g = [m for m in matches if keep(m)]
lo, hi = luck_margin(away_vs_home, g)
print(f"{label}: {len(g)} matches, away {away_vs_home(g):.2f} times as often ({lo:.2f} to {hi:.2f})")
# 4. like with like: defending away sides against defending home sides, attacking against attacking
home_on_top = [m for m in matches if m["HS"] > m["AS"]]
away_on_top = [m for m in matches if m["AS"] > m["HS"]]
defending = lambda a, b: booked_per_foul(a)[1] / booked_per_foul(b)[0] # away when defending / home when defending
attacking = lambda a, b: booked_per_foul(b)[1] / booked_per_foul(a)[0] # away when attacking / home when attacking
(home_att, away_def), (home_def, away_att) = booked_per_foul(home_on_top), booked_per_foul(away_on_top)
print(f"defending: away {away_def:.3f}, home {home_def:.3f}, away {defending(home_on_top, away_on_top):.2f} times "
f"({'{:.2f} to {:.2f}'.format(*luck_margin(defending, home_on_top, away_on_top))})")
print(f"attacking: away {away_att:.3f}, home {home_att:.3f}, away {attacking(home_on_top, away_on_top):.2f} times "
f"({'{:.2f} to {:.2f}'.format(*luck_margin(attacking, home_on_top, away_on_top))})")
# 5. referees: is it a few, or nearly all? (counts only; no referee is named)
by_ref = defaultdict(list)
for m in matches:
if m["referee"]:
by_ref[m["referee"]].append(m)
regulars = {k: g for k, g in by_ref.items() if len(g) >= 100}
print(f"{len(by_ref)} referees; {len(regulars)} with 100+ matches; "
f"{sum(away_vs_home(g) > 1 for g in regulars.values())} of them book away fouls more often")
def spread(pairs): # how far the regulars differ from each other, on a log scale
groups = defaultdict(list)
for ref, m in pairs:
groups[ref].append(m)
v = [log(away_vs_home(g)) for g in groups.values()]
return sqrt(mean([(x - mean(v)) ** 2 for x in v]))
pairs = [(ref, m) for ref, g in regulars.items() for m in g]
seen = spread(pairs)
refs = [ref for ref, _ in pairs]
shuffled = []
for _ in range(500): # hand the same matches out to referees at random: how spread out does luck alone make them?
rnd.shuffle(refs)
shuffled.append(spread(list(zip(refs, (m for _, m in pairs)))))
print(f"spread between regular referees {seen:.3f}; luck alone {mean(shuffled):.3f}; "
f"as spread out by luck alone in {sum(x >= seen for x in shuffled) / len(shuffled):.0%} of reshuffles")
Further reading
- Per Pettersson-Lidbom and Mikael Priks, Behavior under social pressure: empty Italian stadiums and referee bias (Economics Letters, 2010): when some Italian clubs had to play home matches in empty stadiums in 2007, referees showed home bias only when spectators were present.
- Marek Endrich and Tobias Gesche, Home-bias in referee decisions: evidence from "ghost matches" during the Covid19 pandemic (Economics Letters, 2020): in Germany's top two divisions, home sides got fewer fouls and yellow cards given against them than away sides before the pandemic, and lost that edge in the ghost matches.