Swansea City produced a performance of tremendous character, and no little quality, but were denied just a third FA Cup semi-final appearance in heartbreaking fashion by Manchester City.
The Swans had stunned their much-fancied opponents by sweeping into a 2-0 lead inside half an hour.
Matt Grimes converted for the spot for the first, before Bersant Celina finished a flowing Swansea attack against his old club.
The score stayed that way until the 69th minute when Bernardo Silva pulled a goal back with a fine volley, before a controversial penalty allowed City to level.
Cameron Carter-Vickers was harshly ruled to have fouled Raheem Sterling, and Sergio Aguero’s penalty found the net off the back of Kristoffer Nordfeldt.
That left the tie heading for extra-time but, with two minutes remaining, Aguero expertly headed Bernardo Silva’s cross into the net.
It was harsh on the Swans, who had shown moments of genuine quality against their much-vaunted in-form opponents, but there will be no trip to Wembley for Graham Potter and his side.
Even so, they can be tremendously proud of their performance in front of a passionate and vocal Liberty crowd.
Swansea had brought in Jay Fulton for Kyle Naughton, with Grimes moving into defence.
The visitors had the game’s first chance in the fifth minute as Leroy Sane skipped into space and got away a fierce strike that Nordfeldt did well to parry, with Riyad Mahrez heading the follow-up wide.
Swansea responded with a fine passage of play that really got the crowd going.
Sharp one-touch football freed Daniel James down the left and he cut inside to offer Celina the chance to shoot at goal, but the midfielder tried to cut inside and the chance was gone.
James then produced a fantastic piece of tracking at the other end, sprinting to get back and crowd out Kyle Walker from a threatening City counter.
Nordfeldt made a tremendous save in the 14th minute to block Bernardo Silva’s well-struck volley from an inviting Sane cross.
Even against opposition of such undoubted class and quality there were moments of real encouragement for the hosts, and they again stretched City as Celina sent Wayne Routledge in but the winger could not get a strike away.
And they took the lead in the 20th minute through Grimes, who had against all expectations being operating in the centre of defence.
Mike van der Hoorn’s long ball was superbly controlled by Connor Roberts to cut inside Fabian Delph and, as they entered the area the City man fouled the Wales international.
Referee Andre Marriner pointed to the spot and Grimes stepped up to emphatically beat Ederson from the spot.
Incredibly Swansea doubled their lead nine minutes later with a superbly worked team goal.
George Byers and Celina sent James scampering away to find Nathan Dyer in support.
The winger fed Celina, who had carried on his run, and the former City man swept the ball home with aplomb.
City sought an immediate response but were denied as Nordfeldt was equal to another Bernardo Silva volley, and David Silva was soon frustrated as a combination of keeper and defenders bundled another effort wide.
Swansea retained their two-goal advantage to the break, and they were given a rapturous reception as they headed down the tunnel.
And the hosts opened the second half brightly, Fulton winning the ball and sending Celina on a driving run that ended with him flashing the ball over the bar.
City piled on the pressure, Grimes shovelling a Walker cross to safety and a succession of blocks just about saw out another prolonged spell of pressure from the top-flight champions.
Guardiola sent on Oleksandr Zinchenko and Raheem Sterling for Sane and Delph.
Swansea were being pushed deeper and deeper and were being limited to brief counter-attacks, with one lovely, flowing break ending with Ederson racing from his line to deny James’ speed.
The visitors made their final change with 27 minutes remaining, Aguero replacing Mahrez but Swansea felt they should have had the chance to further extend their lead seconds after the Argentinian’s arrival.
James appeared to be shoved by Aymeric Laporte as they contested a ball, but play was waved on to the frustration of the home crowd.
And City pulled one back in the 68th minute through Bernardo Silva. The Swans failed to clear after blocking an Aguero shot, and the Portuguese arrowed a shot across Nordfeldt into the far corner.
They were soon on the front foot again, Sterling firing well over when he should have done better from an astute Zinchenko pass.
But they levelled in contentious circumstances with 12 minutes to go.
Cameron Carter-Vickers was adjudged to have brought down Sterling, although a number of Swansea players protested the defender had won the ball, a view replays appeared to back up.
Aguero hit the post with the penalty, but it hit the back of the diving Nordfeldt and found the net.
Nordfeldt then made a brilliant double save to keep Swansea level as he dug out a Garbiel Jesus header and then somehow stopped Aguero’s follow-up.
But it was not enough as a superb delivery from Bernardo Silva was headed into the bottom corner by a stooping Aguero to break Swansea City hearts.
Swansea City: Kristoffer Nordfeldt; Connor Roberts, Mike van der Hoorn, Matt Grimes, Cameron Carter-Vickers; Jay Fulton (Cian Harries 85), George Byers (Declan John 73), Nathan Dyer (Joel Asoro 61), Bersant Celina, Wayne Routledge; Daniel James.
Subs not used: Erwin Mulder, Barrie McKay, Yan Dhanda, Courtney Baker-Richardson.
Manchester City: Ederson; Kyle Walker, Nicolas Otamendi, Aymeric Laporte, Fabian Delph (Oleksandr Zinchenko 57); Bernardo Silva, Ilkay Gundogan, David Silva; Riyad Mahrez (Sergio Aguero 64), Gabriel Jesus, Leroy Sane (Raheem Sterling 57).
Subs not used: Arijanet Muric, Danilo, Phil Foden, Erik Garcia.