diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs
index 1c82df11..ff7db6dd 100644
--- a/binaries/cuprated/src/rpc/json.rs
+++ b/binaries/cuprated/src/rpc/json.rs
@@ -38,7 +38,7 @@ use cuprate_rpc_types::{
         SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse, SyncInfoRequest,
         SyncInfoResponse,
     },
-    misc::{BlockHeader, Status},
+    misc::{BlockHeader, GetBan, Status},
     CORE_RPC_VERSION,
 };
 
@@ -433,9 +433,34 @@ async fn get_bans(
     state: CupratedRpcHandler,
     request: GetBansRequest,
 ) -> Result<GetBansResponse, Error> {
+    let now = Instant::now();
+
+    let bans = address_book::get_bans::<ClearNet>(&mut DummyAddressBook)
+        .await?
+        .into_iter()
+        .map(|ban| {
+            let seconds = if let Some(instant) = ban.unban_instant {
+                instant
+                    .checked_duration_since(now)
+                    .unwrap_or_default()
+                    .as_secs()
+                    .try_into()
+                    .unwrap_or(0)
+            } else {
+                0
+            };
+
+            GetBan {
+                host: ban.address.to_string(),
+                ip: todo!(),
+                seconds,
+            }
+        })
+        .collect();
+
     Ok(GetBansResponse {
         base: ResponseBase::ok(),
-        bans: todo!(),
+        bans,
     })
 }
 
diff --git a/binaries/cuprated/src/rpc/request/address_book.rs b/binaries/cuprated/src/rpc/request/address_book.rs
index 5458c495..b991dce4 100644
--- a/binaries/cuprated/src/rpc/request/address_book.rs
+++ b/binaries/cuprated/src/rpc/request/address_book.rs
@@ -9,6 +9,7 @@ use tower::ServiceExt;
 use cuprate_helper::cast::usize_to_u64;
 use cuprate_p2p_core::{
     services::{AddressBookRequest, AddressBookResponse},
+    types::BanState,
     AddressBook, NetworkZone,
 };
 
@@ -141,7 +142,7 @@ pub(crate) async fn get_ban<Z: NetworkZone>(
 /// [`AddressBookRequest::GetBans`]
 pub(crate) async fn get_bans<Z: NetworkZone>(
     address_book: &mut impl AddressBook<Z>,
-) -> Result<(), Error> {
+) -> Result<Vec<BanState<Z::Addr>>, Error> {
     let AddressBookResponse::GetBans(bans) = address_book
         .ready()
         .await
@@ -153,5 +154,5 @@ pub(crate) async fn get_bans<Z: NetworkZone>(
         unreachable!();
     };
 
-    Ok(todo!())
+    Ok(bans)
 }