Match ends, Fulham 1, Bristol City 2.
Bristol City ended Fulham's four-match winning run in the Championship as they hung on for victory at Craven Cottage.
Midfielder Josh Brownhill scored for the second successive match, heading home Niclas Eliasson's cross from the left after being left unmarked.
The home side had plenty of possession, but Anthony Knockaert was foiled by keeper Dan Bentley when through one-on-one early in the second half.
Famara Diedhiou made it two for the Robins by finishing off a superb move by tapping into an empty net, but Aboubakar Kamara ensured an anxious finish by netting after Bentley had saved Neeskens Kebano's initial shot and then headed against the bar in eight minutes of stoppage time.
Their fifth away win of the season lifted Lee Johnson's City side up to fourth in the table, and level on points with Fulham, who remain third on goal difference only.
Both sides wore black armbands following the recent death of City loan forward Benik Afobe's two-year-old daughter Amora, with the two sets of spectators joining together for a minute's applause.
Top scorer Aleksandar Mitrovic was a subdued figure for Fulham in the first half as the Robins defence kept him in check and it was Ivan Cavaleiro who carried the main threat.
Mitrovic came more into the game after the break, volleying just too high after receiving Stefan Johansen's ball on his chest and then just failing to make contact as he stretched for Knockaert's curling cross, but he was unable to add to his 15 goals so far this term.
And Kamara's effort proved to be only a consolation as Fulham suffered their third home defeat this season, although they were convinced they should have had a penalty when Kebano went down in the box.
Fulham head coach Scott Parker:
"The referee has obviously made a big mistake [in not awarding a penalty] and that can happen, human error. That's when you want VAR in the Championship and it's probably it is an instant reversal of the decision.
"But I am proud of my team. Three or four weeks ago we lost to Hull City here and the stadium cleared out. The fans lost a bit of belief that we could get back in it and I sensed the players did as well.
"But at 2-0 down today with 10 minutes on the clock, we were in the ascendancy and didn't give up, they kept going.
"On another day, the one that hits the bar, the penalty decision, it could turn a different way. I'm proud of the players today."
Bristol City head coach Lee Johnson told BBC Radio Bristol:
"I was pretty calm, I believed in the boys, there was a heart in mouth moment with the penalty appeal at the end but I thought we deserved the win.
"We nullified them, especially in the first half, I'm really pleased with the performance and we've earned a win against a very very good side.
"The second goal is as good as you'll see at any level of football but it's worked on - the movement is about tactical work and as staff that makes you feel really good."
- 12RodákBooked at 90mins
- 4OdoiBooked at 40minsSubstituted forChristieat 87'minutes
- 5MawsonBooked at 90mins
- 8JohansenBooked at 90mins
- 10CairneyBooked at 90mins
- 24KnockaertBooked at 70mins
- 25OnomahSubstituted forKamaraat 68'minutes
- 19CavaleiroSubstituted forKebanoat 82'minutes
- 36De La Torre
- 43S Sessegnon
- 2HuntBooked at 90minsSubstituted forMooreat 90+4'minutes
- 4NagySubstituted forSmithat 87'minutes
- 19EliassonBooked at 57minsSubstituted forO'Dowdaat 78'minutes
- 32Lopes Pereira
- Jeremy Simpson
- Shots on Target
Second Half ends, Fulham 1, Bristol City 2.
Alfie Mawson (Fulham) is shown the yellow card.
Marek Rodák (Fulham) is shown the yellow card.
Foul by Marek Rodák (Fulham).
Famara Diédhiou (Bristol City) wins a free kick in the defensive half.
Corner, Fulham. Conceded by Nathan Baker.
Neeskens Kebano (Fulham) hits the bar with a header from the centre of the box. Assisted by Cyrus Christie with a cross.
Attempt blocked. Anthony Knockaert (Fulham) left footed shot from the right side of the box is blocked. Assisted by Aboubakar Kamara.
Stefan Johansen (Fulham) is shown the yellow card.
Substitution, Bristol City. Taylor Moore replaces Jack Hunt.
Jack Hunt (Bristol City) is shown the yellow card.
Tom Cairney (Fulham) is shown the yellow card.
Tim Ream (Fulham) wins a free kick in the defensive half.
Foul by Famara Diédhiou (Bristol City).
Aleksandar Mitrovic (Fulham) wins a free kick in the attacking half.
Foul by Callum O'Dowda (Bristol City).
Attempt missed. Alfie Mawson (Fulham) header from the centre of the box is too high. Assisted by Anthony Knockaert with a cross following a corner.
Corner, Fulham. Conceded by Jack Hunt.
Tom Cairney (Fulham) wins a free kick in the defensive half.