A dramatic equaliser from Zenit St Petersburg four minutes into added time meant holders Chelsea failed to top their Champions League group.
Substitute Magomed Ozdoev scored a stunning half-volley from the edge of the box after Chelsea had come from behind to lead 3-2 with minutes left.
Timo Werner scored in both halves and also set up Romelu Lukaku after Zenit had come from 1-0 down to lead 2-1.
But Ozdoev's strike meant Chelsea finish behind Juventus, who beat Malmo.
Thomas Tuchel's side - whose only defeat of the group stages came in Turin when they lost 1-0 to Juventus - made the perfect start, Werner reacting to poke in the opener within three minutes.
Two goals in quick succession from Claudinho and Sardar Azmoun saw Zenit go in front at the break, before Werner's one-two with Ross Barkley helped tee up Lukaku for Chelsea's second.
Werner, who was a threat for Chelsea throughout, showed composure to make it 3-2 when substitute Christian Pulisic played him in with five minutes remaining.
But Ozdoev's stunning stoppage-time strike ensured Juventus topped Group H, while Zenit finished in third and will go into the Europa League play-offs in February.
Chelsea troubled by Zenit
Timo Werner scored twice and picked up an assist in RussiaTuchel made eight changes for the game in Russia, saying fresh legs were needed to manage a heavy fixtures schedule in December.
Lukaku, returning to the side for the first time since October after injury, lacked sharpness but was in the right place to tap in Werner's cut-back in the second half.
Werner thought he had given Chelsea victory when he slotted in his second late on - anxiously awaiting a check from the video assistant referee for a potential offside.
But Zenit, who had threatened Chelsea on numerous occasions in the first half, remained a threat deep into stoppage time.
Earlier misses from Mason Mount, Werner and Saul will add to Chelsea's disappointment but Zenit also had chances of their own - Azmoun was denied in a one-on-one with Kepa Arrizabalaga in the first half and again from a header in the second.
Chelsea end the group stage with four wins from six games, two points off Juventus.
helpHow to play
Rate players out of 10 throughout or after the game. The rater will close 30 minutes after the final whistle.
Rating range key1 = Give it up10 = Pure perfection
Zenit St Petersburg
Squad number41Player nameKerzhakov
Squad number15Player nameKaravaev
Squad number6Player nameLovren
Squad number44Player nameRakitskiy
Squad number3Player nameDouglas Santos
Squad number5Player nameBarrios
Squad number10Player nameMalcom
Squad number14Player nameKuzyaev
Squad number8Player nameWendel
Squad number11Player nameClaudinho
Squad number7Player nameAzmoun
Squad number4Player nameKrugovoy
Squad number17Player nameMostovoy
Squad number21Player nameErokhin
Squad number22Player nameDzyuba
Squad number27Player nameOzdoev
Chelsea
Squad number1Player nameArrizabalaga
Squad number28Player nameAzpilicueta
Squad number4Player nameChristensen
Squad number31Player nameSarr
Squad number20Player nameHudson-Odoi
Squad number24Player nameJames
Squad number18Player nameBarkley
Squad number17Player nameSaúl
Squad number19Player nameMount
Squad number9Player nameLukaku
Squad number11Player nameWerner
Squad number3Player nameAlonso
Squad number10Player namePulisic
Squad number22Player nameZiyech
Squad number29Player nameHavertz
Line-ups
Zenit St Petersburg
Formation 4-1-4-1
41Kerzhakov
15Karavaev6Lovren44Rakitskiy3dos Santos Justino de Melo
5Barrios
10Malcom14Kuzyaev8Valle da Silva11Rodrigues Parisi Leonel
7Azmoun
41Kerzhakov15Karavaev6LovrenBooked at 60mins44RakitskiySubstituted forKrugovoyat 66'minutes3dos Santos Justino de Melo5Barrios10MalcomSubstituted forErokhinat 79'minutes14KuzyaevSubstituted forOzdoevat 79'minutes8Valle da SilvaSubstituted forMostovoyat 51'minutes11Rodrigues Parisi Leonel7AzmounSubstituted forDzyubaat 79'minutesSubstitutes
4Krugovoy17Mostovoy19Sutormin21Erokhin22Dzyuba27Ozdoev64Kravtsov71Odoevskiy85Kuznetsov91Byazrov94KhotulevChelsea
Formation 3-4-1-2
1Arrizabalaga
28Azpilicueta4Christensen31Sarr
20Hudson-Odoi24James18Barkley17Saúl
19Mount
9Lukaku11Werner
1Arrizabalaga28Azpilicueta4Christensen31Sarr20Hudson-OdoiBooked at 37minsSubstituted forPulisicat 65'minutes24James18BarkleySubstituted forZiyechat 65'minutes17SaúlSubstituted forAlonsoat 75'minutes19Mount9LukakuSubstituted forHavertzat 75'minutes11WernerSubstitutes
2Rüdiger3Alonso6Thiago Silva10Pulisic12Loftus-Cheek13Bettinelli16Mendy22Ziyech29HavertzReferee:Serdar GözübüyükLive Text
Match ends, Zenit St Petersburg 3, Chelsea 3.
Second Half ends, Zenit St Petersburg 3, Chelsea 3.
Hand ball by Marcos Alonso (Chelsea).
Goal! Zenit St Petersburg 3, Chelsea 3. Magomed Ozdoev (Zenit St Petersburg) right footed shot from outside the box to the top left corner.
Marcos Alonso (Chelsea) wins a free kick in the defensive half.
Foul by Aleksandr Erokhin (Zenit St Petersburg).
Malang Sarr (Chelsea) wins a free kick on the left wing.
Foul by Artem Dzyuba (Zenit St Petersburg).
Goal! Zenit St Petersburg 2, Chelsea 3. Timo Werner (Chelsea) right footed shot from the centre of the box to the centre of the goal. Assisted by Christian Pulisic.
Attempt saved. Timo Werner (Chelsea) header from the left side of the box is saved in the centre of the goal. Assisted by Christian Pulisic with a cross.
Attempt missed. Douglas Santos (Zenit St Petersburg) left footed shot from outside the box is close, but misses to the right following a corner.
Attempt blocked. Aleksandr Erokhin (Zenit St Petersburg) header from the centre of the box is blocked. Assisted by Daniil Krugovoy with a cross.
Corner, Zenit St Petersburg. Conceded by César Azpilicueta.
Corner, Chelsea. Conceded by Vyacheslav Karavaev.
Attempt blocked. Timo Werner (Chelsea) left footed shot from the left side of the box is blocked. Assisted by Kai Havertz.
Substitution, Zenit St Petersburg. Magomed Ozdoev replaces Daler Kuzyaev.
Substitution, Zenit St Petersburg. Aleksandr Erokhin replaces Malcom.
Substitution, Zenit St Petersburg. Artem Dzyuba replaces Sardar Azmoun because of an injury.
Substitution, Chelsea. Kai Havertz replaces Romelu Lukaku.
Substitution, Chelsea. Marcos Alonso replaces Saúl Ñíguez.