diff --git a/examples/key_value_store.rs b/examples/key_value_store.rs
index 8447cee5..324b3de4 100644
--- a/examples/key_value_store.rs
+++ b/examples/key_value_store.rs
@@ -52,7 +52,7 @@ struct State {
 
 async fn get(
     _req: Request<Body>,
-    params: extract::UrlParams,
+    params: extract::UrlParamsMap,
     state: extract::Extension<SharedState>,
 ) -> Result<Bytes, Error> {
     let state = state.into_inner();
@@ -69,7 +69,7 @@ async fn get(
 
 async fn set(
     _req: Request<Body>,
-    params: extract::UrlParams,
+    params: extract::UrlParamsMap,
     value: extract::BytesMaxLength<{ 1024 * 5_000 }>, // ~5mb
     state: extract::Extension<SharedState>,
 ) -> Result<response::Empty, Error> {
diff --git a/src/error.rs b/src/error.rs
index fcfae63c..dcfa50bc 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -39,6 +39,9 @@ pub enum Error {
     #[error("response failed with status {0}")]
     Status(StatusCode),
 
+    #[error("invalid URL param. Expected something of type `{type_name}`")]
+    InvalidUrlParam { type_name: &'static str },
+
     #[error("unknown URL param `{0}`")]
     UnknownUrlParam(String),
 }
@@ -65,7 +68,8 @@ where
     match error {
         Error::DeserializeRequestBody(_)
         | Error::QueryStringMissing
-        | Error::DeserializeQueryString(_) => make_response(StatusCode::BAD_REQUEST),
+        | Error::DeserializeQueryString(_)
+        | Error::InvalidUrlParam { .. } => make_response(StatusCode::BAD_REQUEST),
 
         Error::Status(status) => make_response(status),
 
diff --git a/src/extract.rs b/src/extract.rs
index 998bc232..d1c6b41c 100644
--- a/src/extract.rs
+++ b/src/extract.rs
@@ -184,9 +184,9 @@ impl<const N: u64> FromRequest for BytesMaxLength<N> {
     }
 }
 
-pub struct UrlParams(HashMap<String, String>);
+pub struct UrlParamsMap(HashMap<String, String>);
 
-impl UrlParams {
+impl UrlParamsMap {
     pub fn get(&self, key: &str) -> Result<&str, Error> {
         if let Some(value) = self.0.get(key) {
             Ok(value)
@@ -194,9 +194,18 @@ impl UrlParams {
             Err(Error::UnknownUrlParam(key.to_string()))
         }
     }
+
+    pub fn get_typed<T>(&self, key: &str) -> Result<T, Error>
+    where
+        T: std::str::FromStr,
+    {
+        self.get(key)?.parse().map_err(|_| Error::InvalidUrlParam {
+            type_name: std::any::type_name::<T>(),
+        })
+    }
 }
 
-impl FromRequest for UrlParams {
+impl FromRequest for UrlParamsMap {
     type Future = future::Ready<Result<Self, Error>>;
 
     fn from_request(req: &mut Request<Body>) -> Self::Future {