Mahmoud Dahoud's 89th-minute winner on Saturday after Jude Bellingham equalized in the 86th moved Dortmund six points behind Bayern Munich a day after the league leader's 2-1 loss at home to Borussia Mönchengladbach.
A fired up Erling Haaland was a factor in all three goals for Dortmund, which might easily have been four goals down in Frankfurt.
"It's very annoying," Dortmund defender Mats Hummels said.
"That's the big issue for us, that we give away goals for nothing, that we always concede in situations were no goals should be conceded.
"That was the case with both goals today. It was the case two or three times in Berlin (3-2 defeat to Hertha before the winter break), and it was the case against Bayern, unfortunately twice through me. And that happens way too often, and then you don't always win. This stability is something we need to make our top priority if we want to have a chance for anything."
Colombian forward Rafael Borré opened the scoring with a simple finish to Filip Kostic's free kick in the 15th, then doubled the lead in the 24th after more lax defending.
Evan Ndicka struck the post for Frankfurt before Dahoud gifted Frankfurt's Jesper Lindström another huge opportunity in the 34th. But the midfielder shot wide.
Haaland's and Julian Brandt's efforts showed some hope for the visitors around the hour mark. Thorgan Hazard pulled a goal back in the 71st after Haaland sent him through.
The Norwegian was again involved before Thomas Meunier set up Jude Bellingham for the equalizer, and again before Dahoud curled in the late winner.
Freiburg and Bayer Leverkusen dropped points after leading.
Patrik Schick's 17th goal of the season wasn't enough for Leverkusen, which was fortunate to emerge with a 2-2 draw against Union Berlin as the visitor twice hit the post late on.
Schick rewarded the home team's early dominance against Union with the opener in the 39th, his ninth goal in their last five Bundesliga games.
However, the visitors equalized before the break. Lukáš Hrádecký pulled off two fine saves in quick succession to deny Christoph Trimmel then Kevin Behrens, but was powerless to stop Grischa Prömel scoring at the third attempt.
Union coach Urs Fischer made two changes at the break and Prömel scored again in the 49th. Andreas Luthe thrice denied Leverkusen a response.
Union's Max Kruse struck the top corner of the post in the 78th, then Jonathan Tah finally equalized in the 84th with a header to Karim Bellarabi's cross.
Union came closer to a late winner, with Andreas Voglsammer hitting the post, then missing another chance in injury time, before Bastian Oczipka struck the post again.
Freiburg, which spent the league's winter break in third place, drew against relegation-threatened Arminia Bielefeld 2-2 despite scoring first through Janik Haberer and Jeong Woo-yeong.
Leipzig overcame a host of coronavirus infections to beat 10-man Mainz 4-1.
American forward Ricardo Pepi made his debut as a second-half substitute in a 3-1 defeat at Hoffenheim.
Also, Stuttgart drew at last-placed Greuther Fürth 0-0.