Elliott, on fresher tires, got to the inside of Keselowski through Turns 5 and 6 on Lap 49 to take the lead and held him off for the stage victory.
Clint Bowyer ended up third, Jimmie Johnson was fourth and Kevin Harvick fifth.
Following the break between Stages 1 and 2, many drivers elected to pit but Joey Logano stayed to inherit the lead.
Kyle Larson pit outside the box during his stop and was assessed a one-lap penalty.
On the restart on Lap 28, Logano led the way followed by Keselowski, Harvick and Elliott.
Elliott out-braked Harvick entering the back chicane on Lap 30 to take over the second position.
Elliott moved around Logano on Lap 31 through Turn 7 to grab the lead for the first time in the race.
Keselowski was forced to pit under green on Lap 33 after flat-spotting his tires while braking through the back chicane.
With 15 laps remaining in the second stage, Elliott had moved out to a 3.4-second lead over Harvick as Daniel Suarez ran third. Logano was fourth and Kyle Busch ran fifth.
On Lap 38, Johnson had to pit under green for a flat tire, while Logano made a second stop after hitting the tire barrier in Turn 3.
With 10 laps to go in the second stage, Elliott’s lead over Harvick was 4.5 seconds. Suarez remained in third, Kyle Busch fourth and Martin Truex Jr. ran fifth.
Alex Bowman got into Bubba Wallace exiting the back chicane on Lap 41 and turned Wallace around to bring out a caution.
Most of the lead-lap cars elected to pit but Bowyer stayed out and inherited the lead. On the restart on Lap 45, Bowyer led the way followed by Michael McDowell and Keselowski.
Keselowski got around Bowyer after exiting the infield on Lap 46 to take the lead for the first time in the race.
Elliott got past McDowell on Lap 47 to move into the third spot. One lap later, he got around Bowyer to move into second, less than a second behind Keselowski.
Elliott finally worked his way around Keselowski in Turn 6 on Lap 49 to retake the lead.