The 20-year-old enjoyed an impressive season with Betis, scoring twice in 30 league appearances, and Madrid and Barca both contacted Betis for him.
Betis offered him a new deal, but president Angel Haro revealed on Monday that the player informed them of his decision to join Zinedine Zidane's side after agreeing a six-year contract, leaving the clubs to decide on a transfer fee.
"Real Madrid and Real Betis have reached an agreement over the transfer of Dani Ceballos, who is tied to the club for the next six seasons," a statement from Real read.
Ceballos is Madrid's second signing of the close-season, having already secured Theo Hernandez from Atletico Madrid for €24m.
He joins just days after James Rodriguez departed for Bayern Munich and will be presented as a Real Madrid player at the Santiago Bernabeu on Thursday before joining the club's pre-season tour of the United States.