diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md
index c8d65e39..43560746 100644
--- a/actix-http/CHANGES.md
+++ b/actix-http/CHANGES.md
@@ -4,6 +4,10 @@
 ### Changed
 * Change compression algorithm features flags. [#2250]
 
+### Removed
+* `downcast` and `downcast_get_type_id` macros. [#2291]
+
+[#2291]: https://github.com/actix/actix-web/pull/2291
 [#2250]: https://github.com/actix/actix-web/pull/2250
 
 
diff --git a/actix-http/src/lib.rs b/actix-http/src/lib.rs
index 924d5441..d22e1ee4 100644
--- a/actix-http/src/lib.rs
+++ b/actix-http/src/lib.rs
@@ -27,9 +27,6 @@
 #[macro_use]
 extern crate log;
 
-#[macro_use]
-mod macros;
-
 pub mod body;
 mod builder;
 pub mod client;
diff --git a/actix-http/src/macros.rs b/actix-http/src/macros.rs
deleted file mode 100644
index be8e63d6..00000000
--- a/actix-http/src/macros.rs
+++ /dev/null
@@ -1,110 +0,0 @@
-#[macro_export]
-#[doc(hidden)]
-macro_rules! downcast_get_type_id {
-    () => {
-        /// A helper method to get the type ID of the type
-        /// this trait is implemented on.
-        /// This method is unsafe to *implement*, since `downcast_ref` relies
-        /// on the returned `TypeId` to perform a cast.
-        ///
-        /// Unfortunately, Rust has no notion of a trait method that is
-        /// unsafe to implement (marking it as `unsafe` makes it unsafe
-        /// to *call*). As a workaround, we require this method
-        /// to return a private type along with the `TypeId`. This
-        /// private type (`PrivateHelper`) has a private constructor,
-        /// making it impossible for safe code to construct outside of
-        /// this module. This ensures that safe code cannot violate
-        /// type-safety by implementing this method.
-        ///
-        /// We also take `PrivateHelper` as a parameter, to ensure that
-        /// safe code cannot obtain a `PrivateHelper` instance by
-        /// delegating to an existing implementation of `__private_get_type_id__`
-        #[doc(hidden)]
-        fn __private_get_type_id__(
-            &self,
-            _: PrivateHelper,
-        ) -> (std::any::TypeId, PrivateHelper)
-        where
-            Self: 'static,
-        {
-            (std::any::TypeId::of::<Self>(), PrivateHelper(()))
-        }
-    };
-}
-
-//Generate implementation for dyn $name
-#[doc(hidden)]
-#[macro_export]
-macro_rules! downcast {
-    ($name:ident) => {
-        /// A struct with a private constructor, for use with
-        /// `__private_get_type_id__`. Its single field is private,
-        /// ensuring that it can only be constructed from this module
-        #[doc(hidden)]
-        pub struct PrivateHelper(());
-
-        impl dyn $name + 'static {
-            /// Downcasts generic body to a specific type.
-            pub fn downcast_ref<T: $name + 'static>(&self) -> Option<&T> {
-                if self.__private_get_type_id__(PrivateHelper(())).0
-                    == std::any::TypeId::of::<T>()
-                {
-                    // SAFETY: external crates cannot override the default
-                    // implementation of `__private_get_type_id__`, since
-                    // it requires returning a private type. We can therefore
-                    // rely on the returned `TypeId`, which ensures that this
-                    // case is correct.
-                    unsafe { Some(&*(self as *const dyn $name as *const T)) }
-                } else {
-                    None
-                }
-            }
-
-            /// Downcasts a generic body to a mutable specific type.
-            pub fn downcast_mut<T: $name + 'static>(&mut self) -> Option<&mut T> {
-                if self.__private_get_type_id__(PrivateHelper(())).0
-                    == std::any::TypeId::of::<T>()
-                {
-                    // SAFETY: external crates cannot override the default
-                    // implementation of `__private_get_type_id__`, since
-                    // it requires returning a private type. We can therefore
-                    // rely on the returned `TypeId`, which ensures that this
-                    // case is correct.
-                    unsafe {
-                        Some(&mut *(self as *const dyn $name as *const T as *mut T))
-                    }
-                } else {
-                    None
-                }
-            }
-        }
-    };
-}
-
-#[cfg(test)]
-mod tests {
-    #![allow(clippy::upper_case_acronyms)]
-
-    trait MB {
-        downcast_get_type_id!();
-    }
-
-    downcast!(MB);
-
-    impl MB for String {}
-    impl MB for () {}
-
-    #[actix_rt::test]
-    async fn test_any_casting() {
-        let mut body = String::from("hello cast");
-        let resp_body: &mut dyn MB = &mut body;
-        let body = resp_body.downcast_ref::<String>().unwrap();
-        assert_eq!(body, "hello cast");
-        let body = &mut resp_body.downcast_mut::<String>().unwrap();
-        body.push('!');
-        let body = resp_body.downcast_ref::<String>().unwrap();
-        assert_eq!(body, "hello cast!");
-        let not_body = resp_body.downcast_ref::<()>();
-        assert!(not_body.is_none());
-    }
-}