Nach der Führung durch einen Hackentreffer von Karim Benzema (13.) erhöhte Toni Kroos in der 28. Minute per abgefälschtem Freistoß.
Óscar Mingueza (60.) erzielte nur noch den Anschluss für Barcelona. In der 90. Minute sah Madrids Casemiro die Gelb-Rote Karte.
Durch den sechsten Pflichtspielsieg in Serie schob sich Real zumindest für eine Nacht am punktgleichen Stadtrivalen Atlético vorbei. Der Spitzenreiter kann bereits mit einem Remis am Sonntagabend bei Betis Sevilla die Spitzenposition wieder übernehmen.
Barcelona fiel hinter Real zurück und ist nur noch Tabellendritter.
Für die Madrilenen war es eine erfolgreiche Generalprobe für das Viertelfinal-Rückspiel in der Champions League am Mittwoch beim FC Liverpool, das erste Duell gewann Real mit 3:1.
dpa/sp