Wychowanek Korony Kielce[1]. W latach 2009–2012 występował w barwach kieleckiego klubu w rozgrywkach Młodej Ekstraklasy (rozegrał 34 mecze).
W sierpniu 2012 został wypożyczony do Stali Mielec[2]. W sezonie 2012/2013, w którym rozegrał 26 meczów, wywalczył z nią awans do II ligi. W 2013 został wykupiony przez Stal z Korony Kielce za 25 tys. zł[1]. W sezonie 2015/2016, w którym mielecka drużyna uzyskała promocję do I ligi, rozegrał 30 meczów i strzelił trzy bramki w spotkaniach z Legionovią Legionowo (1:1; 13 września 2015), Polonią Bytom (4:3; 21 listopada 2015) i Wisłą Puławy (2:1; 21 maja 2016). Od stycznia 2016 pełnił funkcję kapitana Stali Mielec (zastąpił w tej roli Sebastiana Dudę)[3]. W sezonie 2016/2017 rozegrał w I lidze 10 meczów i zdobył dwie bramki: pierwszą 5 sierpnia 2016 w zremisowanym spotkaniu z Górnikiem Zabrze (1:1), drugą 30 października 2016 w wygranym meczu z Zagłębiem Sosnowiec (2:0). W lutym 2017 został wybrany najlepszym piłkarzem Podkarpacia w 2016[4].
W styczniu 2017 przeszedł na zasadzie transferu definitywnego do Korony Kielce (kielecki klub wpłacił kwotę odstępnego zawartą w umowie zawodnika ze Stalą), z którą podpisał półtoraroczny kontrakt z opcją przedłużenia o kolejny sezon[5]. W jej barwach 3 marca 2017 zadebiutował w Ekstraklasie w spotkaniu z Górnikiem Łęczna (2:1), w którym zmienił w 71. minucie Bartosza Rymaniaka. Pierwszą bramkę w najwyższej klasie rozgrywkowej strzelił 19 marca 2017 w meczu z Cracovią (3:0). Gol ten – zdobyty strzałem z ok. 30 metrów – został uznany najładniejszym trafieniem 26. kolejki Ekstraklasy[6] i najładniejszym trafieniem miesiąca w Ekstraklasie[7]. We wrześniu 2017 przedłużył kontrakt z Koroną do końca czerwca 2020[8]. W sezonie 2017/2018 rozegrał w lidze 28 meczów, wystąpił ponadto w czterech spotkaniach Pucharu Polski. W końcówce rozgrywek pauzował z powodu zapalenia spojenia łonowego[9].22 lipca w 2020 roku przeszedł za darmo do Zagłębie Lubin i będzie grał tam od sezonu 2020/21