Bottas headed the timesheets in both FP1 and FP2 at Portimao, and was able to maintain his advantage over Hamilton in the final practice session on Saturday morning.
After both Mercedes drivers reported a lack of grip and struggles getting up to speed at Portimao on Friday, they were quickly able to beat the benchmark set during a messy second practice session that was interrupted by red flags and stoppages.
Bottas and Hamilton opted to focus on soft compound tyre running through the session, trading fastest times back and forth.
Hamilton was able to set the initial pace for Mercedes, only for Bottas to hit back and ultimately set a time of 1m16.654s to edge out his teammate by 0.026 seconds.
Although the lap was set with 25 minutes remaining in the session, it was enough to give Bottas P1 as drivers focused on higher fuel runs towards the end of FP3.
Hamilton lost one of his final qualifying simulations on the soft compound tyre after making a mistake at Turn 8, causing him to run into the gravel.
Max Verstappen was left to settle for third place for Red Bull, but briefly took top spot after beating Hamilton's initial benchmark, only for his time to be deleted after he exceeded track limits at Turn 1.
The Dutchman ultimately finished the session 0.158 seconds shy of Bottas' time, albeit setting his best lap on the medium compound tyre.
A number of drivers running on the soft tyres reported they were struggling with tyre warm-up, continuing the trend from yesterday's practice running that saw most set a fastest time on their second flying lap of a run.
Pierre Gasly bounced back from his fiery end to Friday's running by finishing fourth for AlphaTauri, lapping within three tenths of a second of Bottas' fastest time.
Alexander Albon took fifth in the sister Red Bull car, two tenths back from teammate Verstappen, while Charles Leclerc led Ferrari's charge in sixth. Leclerc suffered one early spin at Turn 14, and reported late in the session that he could hear Hamilton's team radio in the cockpit.
McLaren drivers Carlos Sainz and Lando Norris took seventh and ninth place respectively, split by the Racing Point of Sergio Perez, while Esteban Ocon rounded out the top 10 for Renault.
Sebastian Vettel finished 11th for Ferrari, half a second back from teammate Leclerc. Vettel reported a loose drain cover he had run over at the exit of Turn 14 late in the session, meaning FP3 was red-flagged with one minute remaining on the clock and did not resume.
Vettel was followed by the AlphaTauri of Daniil Kvyat in 12th place and Alfa Romeo's Kimi Raikkonen in 13th.
Daniel Ricciardo could only finish 14th for Renault after reporting an issue with DRS on his car, bringing his session to an early end as he only completed 13 laps.
George Russell took 15th for Williams ahead of Lance Stroll and Antonio Giovinazzi, followed by Haas driver Kevin Magnussen in 18th. Nicholas Latifi and Romain Grosjean propped up the timesheets in 19th and 20th respectively.