Swansea City conceded a stoppage-time equaliser but goals from Jamal Lowe and Andre Ayew still secured a place in the play-offs in Steve Cooper's 100th game in charge at Reading.
The Swans had trailed at the Madejski Stadium as Yakou Meite headed in a 30th-minute opener for a Royals side needing a win to keep their top-six hopes alive.
The visitors, meanwhile, needed a point and Lowe put them on course for that when he knocked in his 14th goal of the season from close range.
Substitute Andre Ayew had helped to create the equaliser, and the Ghanaian then put his side ahead when he calmly fired home from a Jake Bidwell pull-back for his 16th goal this term.
Lowe hit the post, and Reading made the most of the fortune as they levelled through Tomas Esteves in time added on, but it was not enough to prevent Swansea ensuring they will finish in the top six.
The result leaves the Swans fifth in the table on 77 points with two games remaining.
Liam Cullen, Ben Cabango and Conor Hourihane had been restored to the starting line-up by Cooper, with Connor Roberts, Ryan Bennett and Korey Smith dropping to the bench.
There was also a place among the substitutes for Ayew, passed fit to be named in the matchday squad following a hamstring injury.
It was one of the returning trio who should have given Swansea the lead inside a minute.
A short free-kick caught Reading out, and allowed Lowe to whip in a perfect cross for Cabango at the far post, but the centre-half sent his header wide.
It was all Swansea early on, and Wayne Routledge saw a shot blocked over the bar by Royals' captain Liam Moore after more slick build-up play.
Lowe then fired over himself from a decent volleyed effort after a half-cleared corner came to him on the edge of the area.
Nice link work by Cullen and Routledge then gave Lowe some space, but the forward just took too heavy a touch.
And Reading went straight down the other end to take the lead, John Swift was given the time to pick out a cross from a throw-in and Meite arrived to head home via the inside of the far post.
Freddie Woodman then had to make a fine save to deny Lucas Joao, after Hourihane had gifted the ball to the Reading striker 25 yards from goal from a Swansea free-kick.
Cabango made a key challenge on Meite a few moments later, timing his tackle well, knowing a spot-kick would be the outcome of any error of judgement.
Those interventions ensured the visitors trailed by just the solitary goal at the break, and they could have been level inside 70 seconds of the start of the second half.
Lowe drilled a cross towards the penalty spot, and Cullen steered his header agonisingly wide with keeper Rafael completely beaten.
Just before the hour a well-worked corner routine ended with Bidwell flicking the ball on to Marc Guehi, but Moore positioned himself well to stop the defender giving Cullen a simple tap-in.
But Reading remained a threat with Andy Rinomhota hitting the side-netting when unmarked from a Ovie Ejaria cross.
Cooper soon made three changes as Roberts, Morgan Whittaker and Ayew all came on and Cullen, Routledge and Kyle Naughton made way.
And Ayew wasted no time making an instant impact.
A lovely check inside and backheel sent Fulton racing in on goal. The midfielder’s initial shot was saved, but Lowe was on hand to convert the follow-up.
Lowe soon worked Rafael again, turning and getting in a low shot from a Bidwell pass, and then pushed an effort wide after a promising Swansea counter.
But the Swans looked to have struck the decisive blow just seven minutes from time as a flowing attack saw Bidwell break into the box and pick out Ayew to apply the finishing touch.
Lowe nearly added another in the closing moments, but saw his strike come back out off the post, and Reading went up the other end to level as Esteves curled home from the edge of the box.
But, it was not enough to prevent Swansea ensuring they joined Bournemouth, Brentford and Barnsley in the play-offs.
Reading: Rafael Cabral; Andy Yiadom (Tomas Esteves 82), Tom Holmes, Liam Moore (captain), Omar Richards (Sone Aluko 90); Andy Rinomhota, Josh Laurent; Yakou Meite (Alfa Semedo 65), John Swift (Michael Olise 65), Ovie Ejaria (George Puscas 81; Lucas Joao.
Unused Substitutes: Luke Southwood, Sam Baldock, Lewis Gibson, Dejan Tetek.
Swansea City: Freddie Woodman; Kyle Naughton (Connor Roberts 65), Ben Cabango, Marc Guehi, Jake Bidwell; Jay Fulton, Matt Grimes (captain), Conor Hourihane (Korey Smith 86); Wayne Routledge (Morgan Whittaker 65), Liam Cullen (Andre Ayew 65), Jamal Lowe.
Unused Substitutes: Ben Hamer, Ryan Bennett, Yan Dhanda, Joel Latibeaudiere, Ollie Cooper.
Referee: Simon Hooper