Having started his career with Sheffield Wednesday's youth system, O'Donnell progressed to the first team, for which he was largely used as an understudy goalkeeper. He played 20 times for Wednesday between 2006 and 2012, earning a significant amount of first-team appearances elsewhere as he spent time on loan with York City, Buxton, Rotherham United, Oldham Athletic, Grimsby Town, Alfreton Town and Macclesfield Town. He was released in the summer of 2012 and joined Chesterfield. In 2013, following limited first-team appearances, he signed a one-year contract at Walsall.
O'Donnell signed his first professional contract with Wednesday in June 2007.[8] He joined Buxton of the Northern Premier League Premier Division in December 2007 on a one-month loan,[9] where he made two appearances.[10] He joined League Two club Rotherham United on 8 January 2008 on a three-month loan, as back-up for Andy Warrington,[11] but was recalled before the end of the deal as back-up to Wednesday's two first-choice goalkeepers.[12] O'Donnell was then loaned to League One club Oldham Athletic on 14 March 2008 on an emergency seven-day loan.[13] He made his Football League debut the following day at the age of 19 in a match against Luton Town.[14]
He joined Conference Premier club Grimsby Town on 31 August 2010 on a one-month loan.[15] He made his debut on 4 September 2010 against Luton, Grimsby winning 2–0 at home.[16] On 4 February 2011, he joined Alfreton Town on a one-month loan.[17]
He made his debut for Wednesday in a 2–0 defeat away to Southampton on 19 March 2011.[18] On 15 May 2012, O'Donnell was amongst the six first-team players to be released by the club.[19]
Chesterfield
The day following his release, O'Donnell signed for Chesterfield on a one-year contract.[20] After appearing as an unused substitute in the first five matches, he made his debut on 4 September 2012 as an 89th-minute substitute for Tommy Lee in a 2–1 home win over Oldham Athletic.[21] O'Donnell made his first start four days later, in a 2–2 away draw against York City on 8 September 2012.[22] He appeared in the following 14 matches, mainly due to the absence of first-choice goalkeeper Tommy Lee, who was out for eight weeks. After Lee recovered and returned to the first team, O'Donnell was once again the club's back-up goalkeeper.
On 14 January 2013, O'Donnell joined Conference Premier club Stockport County on a one-month loan.[23] O'Donnell had his loan spell extended with the club until 16 April 2013.[24] While at Stockport, he made 20 appearances and established himself as first-choice goalkeeper, but the club was relegated to the Conference North.[25] In the last match of the season, O'Donnell made his first Chesterfield appearance in over six months, a 4–0 home victory over Exeter City.[22]
He was released at the end of that one-year contract, in April 2013, following limited first-team opportunities.[26]
Walsall
Following his release from Chesterfield, O'Donnell signed a one-year contract with League One club Walsall on 18 July 2013.[27] He was voted as their Player of the Year in 2014–15.[28]
Wigan Athletic
On 22 May 2015, O'Donnell signed a three-year contract with League One club Wigan Athletic.[29]
Bristol City
After losing his place to Jussi Jääskeläinen in the Wigan team, he joined Championship club Bristol City on 12 January 2016 on loan until the end of 2015–16 as cover for the injured Frank Fielding.[30] He went straight into the team against Preston North End on the same day, in a 2–1 home defeat.[31] He signed permanently on 1 February 2016, for an undisclosed fee, on a two-and-a-half-year contract.[32]
Rotherham United
He re-signed for Championship club Rotherham United on 19 January 2017, on a two-and-a-half-year contract, for an undisclosed fee.[33]
Northampton Town
O'Donnell signed for League One club Northampton Town on 8 January 2018, on a two-and-a-half-year contract, a for an undisclosed fee.[34]
Bradford City
O'Donnell signed for League One club Bradford City on 27 June 2018 on a two-year contract, having been able to leave Northampton on a free transfer because of a relegation clause in his contract.[35] He was offered a new contract by Bradford City in July 2020, following the expiry of his existing contract,[36] signing a new two-year contract later that month.[37]
He was appointed as Bradford City captain on 4 September 2020.[38]
O'Donnell was released by the club at the end of the 2021–22 season,[39] having not featured for the club since 30 November 2021.[40]
Rochdale
On 18 May 2022, O'Donnell signed a two-year contract with Rochdale which came into effect on 1 July after his contract expired at Bradford City.[41] At the end of the 2022–23 season, O'Donnell was awarded with the Supporters' Player of the Year trophy.[42]
^Williams, Mike; Williams, Tony, eds. (2007). Non-League Club Directory 2008. Kingsbridge: Tony Williams Publications. pp. 176–177. ISBN978-1-869833-57-2.
^Williams, Mike; Williams, Tony, eds. (2011). Non-League Club Directory 2012. Tony Williams Publications. pp. 88–89. ISBN978-1-869833-70-1.
^Williams; Williams (eds.). Non-League Club Directory 2012. pp. 28–29.