It looked routine for Madrid early on. Vinicius Junior continued his strong form by opening the scoring inside 20 minutes, calmly finishing from close range after Alvaro Valles parried a powerful effort from Federico Valverde. The goal marked his 13th league strike of the campaign and gave the visitors full control.
Betis struggled to respond for long periods, but just before the break, Madrid were forced to rely on Andriy Lunin. The stand-in goalkeeper produced a series of sharp saves, twice denying Antony to preserve the lead.
Madrid thought they had doubled their advantage when Kylian Mbappe volleyed home from a precise delivery by Trent Alexander-Arnold. However, the effort was ruled out for offside, denying Mbappe a goal on his milestone 100th appearance for the club.
Betis grew into the second half, with substitute Cucho Hernandez testing Lunin, while Valles kept his side alive with key stops from Mbappe and Valverde.
The decisive moment came deep into stoppage time. Hector Bellerin reacted quickest to a loose ball in the box, guiding a composed finish past Lunin to secure a crucial point for the hosts.
After the match, Madrid coach Alvaro Arbeloa expressed frustration at both the result and key decisions.
"When games are this tight, these things can happen. But it's clear we haven't had much luck," he said.
Arbeloa also questioned the build-up to Betis' goal:
"To me, it's very clear. It doesn't take much contact to lose your balance in those situations. But you have to understand football to see it, and that's where we have a problem."
He also pointed to a first-half penalty appeal:
"It was a crystal-clear penalty. An open hand stopping a shot - there's not much else to say. These decisions have a huge impact."
On Mbappe's condition after the match, Arbeloa added:
"He felt some discomfort. We'll see how he progresses over the next few days."