For 21 seasons the head-to-head table never moved — Green Bay .675 inside the division (84-40-2, 2002–22), Detroit .349 at the bottom. Since 2023 it has inverted: Detroit .667, Green Bay .500, Chicago .278 — yet Chicago is the reigning champion at 11-6 despite going 2-4 in the division and 5-19 in it since 2022. Charted on a rolling four-season window from 288 nflverse games, plus the back-loaded 2026 round-robin: 7 of 12 division games from week 10 on.
By C. B. Zakarian · Published August 12, 2026
For two decades the NFC North had an internal pecking order you could set a clock by. From the division's formation in 2002 through 2022, Green Bay went 84-40-2 (.675) in games against the other three members while Detroit went 44-82 (.349) — the top and bottom of the head-to-head table, held for twenty-one consecutive seasons, with Minnesota (67-57-2, .540) and Chicago (55-71, .437) filling the middle. Since 2023 the order has inverted: Detroit is 12-6 (.667) inside the division, Minnesota 10-8 (.556), Green Bay exactly 9-9 (.500), and Chicago 5-13 (.278). The strangest part is who holds the trophy. Chicago enters 2026 as the reigning division champion — and simultaneously owns the worst four-year intra-division ledger of the four, 5-19 (.208) since 2022.
Take every regular-season game played among the four current members — six per team per season, 288 games from 2002 through 2025, ties counted half — and track each team's winning percentage over its last four seasons of those games:
Two lines carry the story. Green Bay's rides above .500 for nearly the whole chart and peaks at .812 in the window ending 2014 — a 19-4-1 stretch across 2011–14 — before descending to exactly 12-12 over 2022–25. Detroit's spends twenty years near the floor and then climbs almost vertically to .708. Chicago's, at .208, ends below anything Detroit posted even in its worst era.
Across the full 2002–2025 file the all-time intra-division table still reads Green Bay 93-49-2 (.653), Minnesota 77-65-2 (.542), Chicago 60-84 (.417), Detroit 56-88 (.389) — one franchise 44 games over break-even across the sample, another 32 under it. The title ledger matches: of the North's 24 championships, Green Bay holds 12, Chicago and Minnesota 5 each, Detroit 2 — both of Detroit's arriving in 2023 and 2024. Green Bay's runs came in blocks: four straight titles 2011–14 and three straight 2019–21, and the file's only perfect 6-0 intra-division seasons before 2024 both belong to Green Bay, in 2011 and 2019. (The champion chain here is derived with the same standings-and-tiebreakers code path used by the division-repeats page, which owns the league-wide repeat-rate question and the full tiebreaker chain; this page just borrows its output for one division.)
The last four seasons broke the pattern in both directions at once: four seasons, three different champions — Minnesota 2022, Detroit 2023 and 2024, Chicago 2025 — and the one team missing from that list is Green Bay, title-less since 2021 despite never dipping below .500 in the division across the stretch.
The 2025 ledgers are the sharpest version of the anomaly. All four teams finished within two games of each other overall, and the internal results point the opposite way from the standings:
So the two teams that went 4-2 inside the division finished behind the team that went 2-4, and the team with the +68 differential finished behind the team at +26. None of that is a paradox — a 17-game record weighs all opponents equally, and Chicago banked its wins outside the division — but it does mean the 2025 title says very little about who controls the head-to-head table. The table says Detroit, 17-7 since 2022; the trophy says Chicago, 5-19 over the same span.
The 2026 schedule file lays out the twelve division games with a distinct tilt toward winter: only 5 of the 12 fall in weeks 1–9, the other seven packed into weeks 10 through 18. The opener is Green Bay at Minnesota in week 1 (September 13) — that game's full head-to-head ledger belongs to the week-1 slate page — followed by Minnesota at Chicago in week 2 and Chicago at Green Bay in week 5. Then the calendar gets theatrical: Chicago at Detroit on Thanksgiving (Thursday, November 26, both teams on four days' rest), Green Bay at Chicago on Christmas Day, a Friday, and a week-18 doubleheader on January 10 — Detroit at Green Bay and Chicago at Minnesota simultaneously, every team playing a division opponent on the final day. Detroit also hosts Green Bay in week 7 off a 14-day layoff against Green Bay's seven, one of the schedule's larger single-game rest splits.
The out-of-division context is lopsided too, per the file's 2025-record-based numbers: Chicago drew the hardest 2026 schedule in the league (opponents .5502, a combined 158-129-2, rank 1) with Green Bay third (.5381) and Minnesota 11th (.5190), while Detroit's slate ranks 27th (.4671, opponents 134-153-2). Season-long net rest runs Chicago +15, Minnesota +4, Detroit +1, Green Bay −2. What preseason SOS is worth — and how much it lies — is the schedule-strength page's question; the league-wide rest and bye ledger lives at the schedule-quirks page; and why division games themselves behave differently is covered by the division-games page. This page makes no win predictions — the site's model forecasts for all four teams live at the predictions page.
One public file: games.csv from nflverse nfldata, bundled at /data/games.csv. The chart and the full console breakdown — era tables, 2025 ledgers, the 2026 division calendar, SOS and rest four-packs — come from explainer_src/make_nfc_north_2026_chart.py; the core is a short loop:
import pandas as pd
from collections import defaultdict
df = pd.read_csv("data_layer/games.csv")
N = ["CHI", "DET", "GB", "MIN"]
g = df[(df.game_type == "REG") & df.home_score.notna()
& df.season.between(2002, 2025)
& df.home_team.isin(N) & df.away_team.isin(N)] # 288 games
rec = defaultdict(lambda: [0, 0, 0]) # (season, team) -> W/L/T
for r in g.itertuples():
if r.home_score > r.away_score:
rec[(r.season, r.home_team)][0] += 1; rec[(r.season, r.away_team)][1] += 1
elif r.home_score < r.away_score:
rec[(r.season, r.away_team)][0] += 1; rec[(r.season, r.home_team)][1] += 1
else:
rec[(r.season, r.home_team)][2] += 1; rec[(r.season, r.away_team)][2] += 1
def era(y0, y1, t):
w, l, ti = (sum(rec[(y, t)][i] for y in range(y0, y1 + 1)) for i in (0, 1, 2))
return f"{t} {w}-{l}" + (f"-{ti}" if ti else "") + f" ({(w + 0.5 * ti) / (w + l + ti):.3f})"
print([era(2002, 2022, t) for t in N]) # GB 84-40-2 (.675) ... DET 44-82 (.349)
print([era(2023, 2025, t) for t in N]) # DET 12-6 (.667) ... CHI 5-13 (.278)
print([era(2022, 2025, t) for t in N]) # DET 17-7 (.708) ... CHI 5-19 (.208)
All figures on this page were computed 2026-08-12 from the file's played games: the head-to-head tables from its 288 intra-division regular-season games (2002–2025), the 2025 ledgers from that season's completed 17-game slates, and the 2026 calendar, SOS, and rest numbers from the file's schedule rows and 2025 results. Nothing here is hand-entered.
Data: nflverse/nfldata, public. The champion chain is verified through the standings-and-tiebreakers implementation shared with the division-repeats page.
Want the code behind these metrics? Work through the 45-chapter NFL analytics tutorial.
Browse tutorials Free tools