It is the first time a Champions League match has been decided by penalties since the 2016 final between Real Madrid and Atletico Madrid.
Trailing 1-0 from the first leg, Mikel Arteta’s Premier League leaders were not at their fluent best against a disciplined Porto side.
Leandro Trossard pulled Arsenal level on aggregate shortly before half-time but neither side could find the killer blow.
The Gunners came into the match with 33 goals in their past eight league games — a winning run that has rocketed them to the top of the Premier League.
But Sergio Conceicao’s men succeeded in frustrating the home team for long periods in the first half, fashioning enough chances of their own make it a nervy night for the expectant fans.
Both sides struggled to settle in a scrappy opening period, with Porto doing their best to slow the game down by taking their time with throw-ins and goal kicks, to the audible frustration of the home crowd.
Arsenal defender Ben White headed over in the fourth minute after the home side’s first sustained attack while captain Martin Odegaard hit the side netting 10 minutes later.
But Porto, who were last crowned European champions under Jose Mourinho in 2004, had a number of openings.
Evanilson whipped a shot at goal from distance that bounced wide and minutes later struck a rising strike that Raya palmed away.
Declan Rice headed just wide and Pepe — the first 41-year-old to play outfield in the Champions League — got the deftest of touches with his head to prevent Kai Havertz from connecting with a White cross at the back post.
Breakthrough
The breakthrough finally came in the 41st minute following good work from Odegaard, who jinked past an opponent and fed Trossard with a perfectly weighted low pass into the box.
Trossard calmly hit a right-footed shot past goalkeeper Diogo Costa and into the far corner of the net to ease the tension.
The visitors, who had never won a match in England in 22 previous attempts, started the second half brightly as Arsenal struggled to impose themselves.
Arsenal thought they had doubled their lead midway through the second half when Odegaard dinked the ball into an empty net but the goal was ruled out for a foul by Havertz on Pepe.
Moments later Porto streamed forward and Raya blocked Francisco Conceicao’s shot from the edge of the penalty area.
Arteta threw on Gabriel Jesus in the 83rd minute and the former Manchester City man nearly scored with his first touch.
As Arsenal pushed for a winner, Bukayo Saka produced a trademark curling effort that was punched back into the middle and Odegaard steered the rebound wide when well-placed.
The home side looked the more dangerous in the early stages of extra-time but Porto remained a threat on the break, with substitute Mehdi Taremi curling wide.
Arteta brought on Eddie Nketiah and Oleksandr Zinchenko for the second period of extra time but neither side could find a winner and it went to penalties.
© Agence France-Presse
Photo: Twitter @ _escobar_p