AC Milan held off Atalanta 3-2 in a lively Serie A clash at San Siro/Giuseppe Meazza, with the hosts sharper in both boxes for most of the night. The points arrived through a first-half penalty from Gonçalo Ramos, a clean finish from Adrien Rabiot, and a towering Mario Gila header after the break. Atalanta rallied late via Gianluca Gaetano and Nikola Krstović, but Milan’s control in key phases proved enough. Dive into the full numbers and timeline on the Sofascore match page, and keep an eye on the broader context in Serie A.
Milan struck first on 24 minutes when Gonçalo Ramos converted from the spot for 1-0. The hosts then doubled the lead just before the interval, with Adrien Rabiot guiding home Diego Moreira’s pass on 43 minutes. At 2-0, Milan had the match where they wanted it, and they went hunting for a third quickly after the restart. They earned another penalty on 57 minutes, but Marco Carnesecchi guessed correctly to save Ramos’s effort. From the resulting attacking phase, Milan stayed on the front foot and Mario Gila made it 3-0 with a thumping header from a corner, teed up by Rabiot.
Atalanta changed the picture from the bench. Nicola Zalewski and Gianluca Gaetano came on at 59 minutes and combined within seven minutes to pull one back, Gaetano finishing with his left for 3-1. The visitors kept asking questions and found a second on 81 minutes when Krstović finished from a Raoul Bellanova assist. They also clipped the woodwork during the push, but the clock was Milan’s friend. Referee Daniele Chiffi allowed five minutes of added time in the second half, yet the equaliser never came.
Numbers behind Milan’s control
Across the 90 minutes Milan owned 56% possession and completed 600 passes to Atalanta’s 464, with accurate passes at 546 to 423. The Rossoneri produced more shots on target, 6 to 4, and posted a stronger expected goals total, 2.45 versus 1.65. They also worked better shooting zones, with 22 touches in the Atalanta box compared to the visitors’ 15. Milan’s crossing was far more effective, completing 3 of 11, while Atalanta went 0 of 17 from wide areas.
Defensively, Milan stacked up 20 tackles to 14 and led interceptions 10 to 7. Duels tilted their way at 56% to 44%, a foundation that limited Atalanta’s fluency in central areas. Recoveries were close at 45 to 43, but the home side kept their structure and transitions cleaner, committing only three fouls to Atalanta’s 10. The visitors did create more big chances overall, four to three, yet they also missed two of them and wasted set-play deliveries. The xG gap and the on-target edge explain why Milan earned the cushion they ultimately needed late on.
Atalanta’s response after the break
The second half was more open, with possession at 52% to 48% in Milan’s favour and shots at 6 to 9 for Atalanta. Both sides landed four efforts on target after the interval, and the xG split (1.45 to 1.25 for Milan) reflects how end-to-end the period became. Sarri’s subs injected purpose: Zalewski delivered an assist and produced two key passes with 0.13 expected assists. Gaetano scored from 0.44 xG just seven minutes after coming on, showing tidy movement between Milan’s lines.
Krstović was another live wire, taking four shots, hitting the woodwork once, and scoring with 0.63 xG on the night. Bellanova’s delivery and ball carrying were constant outlets, and he finished with three key passes and the assist for Krstović. In goal, Carnesecchi kept the visitors alive with three saves, including a standout penalty stop and 0.57 goals prevented. Atalanta also created three big chances in the second half alone, but key details let them down. A 0/12 crossing record after the break told its own story in a match where accuracy in the final ball mattered.
MVP: Adrien Rabiot’s all-action night
Rabiot led Milan by example and by numbers, earning a Sofascore Rating of 9.4. He scored the second goal on 43 minutes and set up Gila for 3-0 with a smart headered assist on 57. The Frenchman created four key passes, including one big chance, and completed 49 of 56 passes while splitting his distribution well between halves of the pitch. He brought bite too, making six tackles with three won and winning eight duels as Milan wrestled control of midfield.
Rabiot’s underlying output pops on the dashboard: 0.50 expected assists, 0.16 expected goals and 0.59 xGOT, plus five recoveries and 70 touches. He carried the ball 20 times for a combined 187 metres and still found energy to press and clear when Atalanta surged late. This was a classic two-way performance, the kind that underpins a big result in Serie A. Others impressed, but from minute one to 90 he was Milan’s reference point.
Brief nods go to Mario Gila (Sofascore Rating 7.8), who scored and posted 66/72 passing and seven accurate long balls, while adding seven recoveries. On the other side, Carnesecchi earned 7.7 with a penalty save and strong positioning, and both Krstović and Gaetano clocked 7.6 thanks to their goals. Rabiot, however, set the tone at both ends of the pitch and closed it.
Key moments and tactical notes
Milan lined up in a 3-4-3 under Rúben Amorim, using width and quick switches to stretch Atalanta’s 4-3-3. That shape leveraged wing play and second balls, reflected by the 48 final-third entries and better crossing returns. The sequence around 57 minutes defined the match: a saved penalty followed by relentless pressure and Gila’s header off a corner routine. Earlier, VAR moments dotted the narrative, including a non-awarded penalty at 22 minutes and another review at 55 minutes before the saved kick two minutes later.
Atalanta were forced into an early defensive reshuffle when Sead Kolašinac went off injured on 20 minutes. The visitors still rallied through the right flank, where Bellanova repeatedly advanced and combined with midfield. They were more dangerous on the dribble after the break, completing 5 of 9, but could not translate wide dominance into accurate crosses. Milan’s press and counter-press limited clean central connections, shown by dispossessions (5 for Milan, 12 for Atalanta) and a 56% duel win rate for the hosts. Referee Daniele Chiffi booked three players and let an entertaining contest breathe at the right times.
For the full breakdown, including xG chains, passing networks and every individual action, visit the Sofascore match center. You can also follow how this result shapes the table and trends across the season on the Serie A page.
Player of the Match
By Sofascore Rating, Adrien Rabiot led the field with 9.4. The fans agreed too: he received 913 of 1200 votes in the poll. Both the top Sofascore Rating and the fans’ pick were Adrien Rabiot, a clean sweep on the night.
AC Milan held off Atalanta 3-2 in a lively Serie A clash at San Siro/Giuseppe Meazza, with the hosts sharper in both boxes for most of the night. The points arrived through a first-half penalty from Gonçalo Ramos, a clean finish from Adrien Rabiot, and a towering Mario Gila header after the break. Atalanta rallied late via Gianluca Gaetano and Nikola Krstović, but Milan’s control in key phases proved enough. Dive into the full numbers and timeline on the Sofascore match page, and keep an eye on the broader context in Serie A.
How the game swung at San Siro
Milan struck first on 24 minutes when Gonçalo Ramos converted from the spot for 1-0. The hosts then doubled the lead just before the interval, with Adrien Rabiot guiding home Diego Moreira’s pass on 43 minutes. At 2-0, Milan had the match where they wanted it, and they went hunting for a third quickly after the restart. They earned another penalty on 57 minutes, but Marco Carnesecchi guessed correctly to save Ramos’s effort. From the resulting attacking phase, Milan stayed on the front foot and Mario Gila made it 3-0 with a thumping header from a corner, teed up by Rabiot.
Atalanta changed the picture from the bench. Nicola Zalewski and Gianluca Gaetano came on at 59 minutes and combined within seven minutes to pull one back, Gaetano finishing with his left for 3-1. The visitors kept asking questions and found a second on 81 minutes when Krstović finished from a Raoul Bellanova assist. They also clipped the woodwork during the push, but the clock was Milan’s friend. Referee Daniele Chiffi allowed five minutes of added time in the second half, yet the equaliser never came.
Numbers behind Milan’s control
Across the 90 minutes Milan owned 56% possession and completed 600 passes to Atalanta’s 464, with accurate passes at 546 to 423. The Rossoneri produced more shots on target, 6 to 4, and posted a stronger expected goals total, 2.45 versus 1.65. They also worked better shooting zones, with 22 touches in the Atalanta box compared to the visitors’ 15. Milan’s crossing was far more effective, completing 3 of 11, while Atalanta went 0 of 17 from wide areas.
Defensively, Milan stacked up 20 tackles to 14 and led interceptions 10 to 7. Duels tilted their way at 56% to 44%, a foundation that limited Atalanta’s fluency in central areas. Recoveries were close at 45 to 43, but the home side kept their structure and transitions cleaner, committing only three fouls to Atalanta’s 10. The visitors did create more big chances overall, four to three, yet they also missed two of them and wasted set-play deliveries. The xG gap and the on-target edge explain why Milan earned the cushion they ultimately needed late on.
Atalanta’s response after the break
The second half was more open, with possession at 52% to 48% in Milan’s favour and shots at 6 to 9 for Atalanta. Both sides landed four efforts on target after the interval, and the xG split (1.45 to 1.25 for Milan) reflects how end-to-end the period became. Sarri’s subs injected purpose: Zalewski delivered an assist and produced two key passes with 0.13 expected assists. Gaetano scored from 0.44 xG just seven minutes after coming on, showing tidy movement between Milan’s lines.
Krstović was another live wire, taking four shots, hitting the woodwork once, and scoring with 0.63 xG on the night. Bellanova’s delivery and ball carrying were constant outlets, and he finished with three key passes and the assist for Krstović. In goal, Carnesecchi kept the visitors alive with three saves, including a standout penalty stop and 0.57 goals prevented. Atalanta also created three big chances in the second half alone, but key details let them down. A 0/12 crossing record after the break told its own story in a match where accuracy in the final ball mattered.
MVP: Adrien Rabiot’s all-action night
Rabiot led Milan by example and by numbers, earning a Sofascore Rating of 9.4. He scored the second goal on 43 minutes and set up Gila for 3-0 with a smart headered assist on 57. The Frenchman created four key passes, including one big chance, and completed 49 of 56 passes while splitting his distribution well between halves of the pitch. He brought bite too, making six tackles with three won and winning eight duels as Milan wrestled control of midfield.
Rabiot’s underlying output pops on the dashboard: 0.50 expected assists, 0.16 expected goals and 0.59 xGOT, plus five recoveries and 70 touches. He carried the ball 20 times for a combined 187 metres and still found energy to press and clear when Atalanta surged late. This was a classic two-way performance, the kind that underpins a big result in Serie A. Others impressed, but from minute one to 90 he was Milan’s reference point.
Brief nods go to Mario Gila (Sofascore Rating 7.8), who scored and posted 66/72 passing and seven accurate long balls, while adding seven recoveries. On the other side, Carnesecchi earned 7.7 with a penalty save and strong positioning, and both Krstović and Gaetano clocked 7.6 thanks to their goals. Rabiot, however, set the tone at both ends of the pitch and closed it.
Key moments and tactical notes
Milan lined up in a 3-4-3 under Rúben Amorim, using width and quick switches to stretch Atalanta’s 4-3-3. That shape leveraged wing play and second balls, reflected by the 48 final-third entries and better crossing returns. The sequence around 57 minutes defined the match: a saved penalty followed by relentless pressure and Gila’s header off a corner routine. Earlier, VAR moments dotted the narrative, including a non-awarded penalty at 22 minutes and another review at 55 minutes before the saved kick two minutes later.
Atalanta were forced into an early defensive reshuffle when Sead Kolašinac went off injured on 20 minutes. The visitors still rallied through the right flank, where Bellanova repeatedly advanced and combined with midfield. They were more dangerous on the dribble after the break, completing 5 of 9, but could not translate wide dominance into accurate crosses. Milan’s press and counter-press limited clean central connections, shown by dispossessions (5 for Milan, 12 for Atalanta) and a 56% duel win rate for the hosts. Referee Daniele Chiffi booked three players and let an entertaining contest breathe at the right times.
For the full breakdown, including xG chains, passing networks and every individual action, visit the Sofascore match center. You can also follow how this result shapes the table and trends across the season on the Serie A page.
Player of the Match
By Sofascore Rating, Adrien Rabiot led the field with 9.4. The fans agreed too: he received 913 of 1200 votes in the poll. Both the top Sofascore Rating and the fans’ pick were Adrien Rabiot, a clean sweep on the night.