diff --git a/awc/src/builder.rs b/awc/src/builder.rs
index 30f203bb..16a4e9cb 100644
--- a/awc/src/builder.rs
+++ b/awc/src/builder.rs
@@ -9,11 +9,13 @@ use actix_rt::net::{ActixStream, TcpStream};
 use actix_service::{boxed, Service};
 
 use crate::{
-    client::{ConnectInfo, Connector, ConnectorService, TcpConnectError, TcpConnection},
+    client::{
+        ClientConfig, ConnectInfo, Connector, ConnectorService, TcpConnectError, TcpConnection,
+    },
     connect::DefaultConnector,
     error::SendRequestError,
     middleware::{NestTransform, Redirect, Transform},
-    Client, ClientConfig, ConnectRequest, ConnectResponse,
+    Client, ConnectRequest, ConnectResponse,
 };
 
 /// An HTTP Client builder
diff --git a/awc/src/client/mod.rs b/awc/src/client/mod.rs
index 0d5c899b..d5854d83 100644
--- a/awc/src/client/mod.rs
+++ b/awc/src/client/mod.rs
@@ -1,6 +1,15 @@
 //! HTTP client.
 
-use http::Uri;
+use std::{convert::TryFrom, rc::Rc, time::Duration};
+
+use actix_http::{error::HttpError, header::HeaderMap, Method, RequestHead, Uri};
+use actix_rt::net::TcpStream;
+use actix_service::Service;
+pub use actix_tls::connect::{
+    ConnectError as TcpConnectError, ConnectInfo, Connection as TcpConnection,
+};
+
+use crate::{ws, BoxConnectorService, ClientBuilder, ClientRequest};
 
 mod config;
 mod connection;
@@ -10,10 +19,6 @@ mod h1proto;
 mod h2proto;
 mod pool;
 
-pub use actix_tls::connect::{
-    ConnectError as TcpConnectError, ConnectInfo, Connection as TcpConnection,
-};
-
 pub use self::connection::{Connection, ConnectionIo};
 pub use self::connector::{Connector, ConnectorService};
 pub use self::error::{ConnectError, FreezeRequestError, InvalidUrl, SendRequestError};
@@ -23,3 +28,176 @@ pub struct Connect {
     pub uri: Uri,
     pub addr: Option<std::net::SocketAddr>,
 }
+
+/// An asynchronous HTTP and WebSocket client.
+///
+/// You should take care to create, at most, one `Client` per thread. Otherwise, expect higher CPU
+/// and memory usage.
+///
+/// # Examples
+/// ```
+/// use awc::Client;
+///
+/// #[actix_rt::main]
+/// async fn main() {
+///     let mut client = Client::default();
+///
+///     let res = client.get("http://www.rust-lang.org")
+///         .insert_header(("User-Agent", "my-app/1.2"))
+///         .send()
+///         .await;
+///
+///      println!("Response: {:?}", res);
+/// }
+/// ```
+#[derive(Clone)]
+pub struct Client(pub(crate) ClientConfig);
+
+#[derive(Clone)]
+pub(crate) struct ClientConfig {
+    pub(crate) connector: BoxConnectorService,
+    pub(crate) default_headers: Rc<HeaderMap>,
+    pub(crate) timeout: Option<Duration>,
+}
+
+impl Default for Client {
+    fn default() -> Self {
+        ClientBuilder::new().finish()
+    }
+}
+
+impl Client {
+    /// Create new client instance with default settings.
+    pub fn new() -> Client {
+        Client::default()
+    }
+
+    /// Create `Client` builder.
+    /// This function is equivalent of `ClientBuilder::new()`.
+    pub fn builder() -> ClientBuilder<
+        impl Service<
+                ConnectInfo<Uri>,
+                Response = TcpConnection<Uri, TcpStream>,
+                Error = TcpConnectError,
+            > + Clone,
+    > {
+        ClientBuilder::new()
+    }
+
+    /// Construct HTTP request.
+    pub fn request<U>(&self, method: Method, url: U) -> ClientRequest
+    where
+        Uri: TryFrom<U>,
+        <Uri as TryFrom<U>>::Error: Into<HttpError>,
+    {
+        let mut req = ClientRequest::new(method, url, self.0.clone());
+
+        for header in self.0.default_headers.iter() {
+            // header map is empty
+            // TODO: probably append instead
+            req = req.insert_header_if_none(header);
+        }
+        req
+    }
+
+    /// Create `ClientRequest` from `RequestHead`
+    ///
+    /// It is useful for proxy requests. This implementation
+    /// copies all headers and the method.
+    pub fn request_from<U>(&self, url: U, head: &RequestHead) -> ClientRequest
+    where
+        Uri: TryFrom<U>,
+        <Uri as TryFrom<U>>::Error: Into<HttpError>,
+    {
+        let mut req = self.request(head.method.clone(), url);
+        for header in head.headers.iter() {
+            req = req.insert_header_if_none(header);
+        }
+        req
+    }
+
+    /// Construct HTTP *GET* request.
+    pub fn get<U>(&self, url: U) -> ClientRequest
+    where
+        Uri: TryFrom<U>,
+        <Uri as TryFrom<U>>::Error: Into<HttpError>,
+    {
+        self.request(Method::GET, url)
+    }
+
+    /// Construct HTTP *HEAD* request.
+    pub fn head<U>(&self, url: U) -> ClientRequest
+    where
+        Uri: TryFrom<U>,
+        <Uri as TryFrom<U>>::Error: Into<HttpError>,
+    {
+        self.request(Method::HEAD, url)
+    }
+
+    /// Construct HTTP *PUT* request.
+    pub fn put<U>(&self, url: U) -> ClientRequest
+    where
+        Uri: TryFrom<U>,
+        <Uri as TryFrom<U>>::Error: Into<HttpError>,
+    {
+        self.request(Method::PUT, url)
+    }
+
+    /// Construct HTTP *POST* request.
+    pub fn post<U>(&self, url: U) -> ClientRequest
+    where
+        Uri: TryFrom<U>,
+        <Uri as TryFrom<U>>::Error: Into<HttpError>,
+    {
+        self.request(Method::POST, url)
+    }
+
+    /// Construct HTTP *PATCH* request.
+    pub fn patch<U>(&self, url: U) -> ClientRequest
+    where
+        Uri: TryFrom<U>,
+        <Uri as TryFrom<U>>::Error: Into<HttpError>,
+    {
+        self.request(Method::PATCH, url)
+    }
+
+    /// Construct HTTP *DELETE* request.
+    pub fn delete<U>(&self, url: U) -> ClientRequest
+    where
+        Uri: TryFrom<U>,
+        <Uri as TryFrom<U>>::Error: Into<HttpError>,
+    {
+        self.request(Method::DELETE, url)
+    }
+
+    /// Construct HTTP *OPTIONS* request.
+    pub fn options<U>(&self, url: U) -> ClientRequest
+    where
+        Uri: TryFrom<U>,
+        <Uri as TryFrom<U>>::Error: Into<HttpError>,
+    {
+        self.request(Method::OPTIONS, url)
+    }
+
+    /// Initialize a WebSocket connection.
+    /// Returns a WebSocket connection builder.
+    pub fn ws<U>(&self, url: U) -> ws::WebsocketsRequest
+    where
+        Uri: TryFrom<U>,
+        <Uri as TryFrom<U>>::Error: Into<HttpError>,
+    {
+        let mut req = ws::WebsocketsRequest::new(url, self.0.clone());
+        for (key, value) in self.0.default_headers.iter() {
+            req.head.headers.insert(key.clone(), value.clone());
+        }
+        req
+    }
+
+    /// Get default HeaderMap of Client.
+    ///
+    /// Returns Some(&mut HeaderMap) when Client object is unique
+    /// (No other clone of client exists at the same time).
+    pub fn headers(&mut self) -> Option<&mut HeaderMap> {
+        Rc::get_mut(&mut self.0.default_headers)
+    }
+}
diff --git a/awc/src/frozen.rs b/awc/src/frozen.rs
index b98d8d5e..14ecf9f3 100644
--- a/awc/src/frozen.rs
+++ b/awc/src/frozen.rs
@@ -12,8 +12,9 @@ use actix_http::{
 };
 
 use crate::{
+    client::ClientConfig,
     sender::{RequestSender, SendClientRequest},
-    BoxError, ClientConfig,
+    BoxError,
 };
 
 /// `FrozenClientRequest` struct represents cloneable client request.
diff --git a/awc/src/lib.rs b/awc/src/lib.rs
index cef8e03d..348d9312 100644
--- a/awc/src/lib.rs
+++ b/awc/src/lib.rs
@@ -124,7 +124,7 @@ pub use actix_http as http;
 pub use cookie;
 
 pub use self::builder::ClientBuilder;
-pub use self::client::Connector;
+pub use self::client::{Client, Connector};
 pub use self::connect::{BoxConnectorService, BoxedSocket, ConnectRequest, ConnectResponse};
 pub use self::frozen::{FrozenClientRequest, FrozenSendBuilder};
 pub use self::request::ClientRequest;
@@ -132,185 +132,4 @@ pub use self::request::ClientRequest;
 pub use self::responses::{ClientResponse, JsonBody, MessageBody, ResponseBody};
 pub use self::sender::SendClientRequest;
 
-use std::{convert::TryFrom, rc::Rc, time::Duration};
-
-use actix_http::{error::HttpError, header::HeaderMap, Method, RequestHead, Uri};
-use actix_rt::net::TcpStream;
-use actix_service::Service;
-
-use self::client::{ConnectInfo, TcpConnectError, TcpConnection};
-
 pub(crate) type BoxError = Box<dyn std::error::Error>;
-
-/// An asynchronous HTTP and WebSocket client.
-///
-/// You should take care to create, at most, one `Client` per thread. Otherwise, expect higher CPU
-/// and memory usage.
-///
-/// # Examples
-/// ```
-/// use awc::Client;
-///
-/// #[actix_rt::main]
-/// async fn main() {
-///     let mut client = Client::default();
-///
-///     let res = client.get("http://www.rust-lang.org")
-///         .insert_header(("User-Agent", "my-app/1.2"))
-///         .send()
-///         .await;
-///
-///      println!("Response: {:?}", res);
-/// }
-/// ```
-#[derive(Clone)]
-pub struct Client(ClientConfig);
-
-#[derive(Clone)]
-pub(crate) struct ClientConfig {
-    pub(crate) connector: BoxConnectorService,
-    pub(crate) default_headers: Rc<HeaderMap>,
-    pub(crate) timeout: Option<Duration>,
-}
-
-impl Default for Client {
-    fn default() -> Self {
-        ClientBuilder::new().finish()
-    }
-}
-
-impl Client {
-    /// Create new client instance with default settings.
-    pub fn new() -> Client {
-        Client::default()
-    }
-
-    /// Create `Client` builder.
-    /// This function is equivalent of `ClientBuilder::new()`.
-    pub fn builder() -> ClientBuilder<
-        impl Service<
-                ConnectInfo<Uri>,
-                Response = TcpConnection<Uri, TcpStream>,
-                Error = TcpConnectError,
-            > + Clone,
-    > {
-        ClientBuilder::new()
-    }
-
-    /// Construct HTTP request.
-    pub fn request<U>(&self, method: Method, url: U) -> ClientRequest
-    where
-        Uri: TryFrom<U>,
-        <Uri as TryFrom<U>>::Error: Into<HttpError>,
-    {
-        let mut req = ClientRequest::new(method, url, self.0.clone());
-
-        for header in self.0.default_headers.iter() {
-            // header map is empty
-            // TODO: probably append instead
-            req = req.insert_header_if_none(header);
-        }
-        req
-    }
-
-    /// Create `ClientRequest` from `RequestHead`
-    ///
-    /// It is useful for proxy requests. This implementation
-    /// copies all headers and the method.
-    pub fn request_from<U>(&self, url: U, head: &RequestHead) -> ClientRequest
-    where
-        Uri: TryFrom<U>,
-        <Uri as TryFrom<U>>::Error: Into<HttpError>,
-    {
-        let mut req = self.request(head.method.clone(), url);
-        for header in head.headers.iter() {
-            req = req.insert_header_if_none(header);
-        }
-        req
-    }
-
-    /// Construct HTTP *GET* request.
-    pub fn get<U>(&self, url: U) -> ClientRequest
-    where
-        Uri: TryFrom<U>,
-        <Uri as TryFrom<U>>::Error: Into<HttpError>,
-    {
-        self.request(Method::GET, url)
-    }
-
-    /// Construct HTTP *HEAD* request.
-    pub fn head<U>(&self, url: U) -> ClientRequest
-    where
-        Uri: TryFrom<U>,
-        <Uri as TryFrom<U>>::Error: Into<HttpError>,
-    {
-        self.request(Method::HEAD, url)
-    }
-
-    /// Construct HTTP *PUT* request.
-    pub fn put<U>(&self, url: U) -> ClientRequest
-    where
-        Uri: TryFrom<U>,
-        <Uri as TryFrom<U>>::Error: Into<HttpError>,
-    {
-        self.request(Method::PUT, url)
-    }
-
-    /// Construct HTTP *POST* request.
-    pub fn post<U>(&self, url: U) -> ClientRequest
-    where
-        Uri: TryFrom<U>,
-        <Uri as TryFrom<U>>::Error: Into<HttpError>,
-    {
-        self.request(Method::POST, url)
-    }
-
-    /// Construct HTTP *PATCH* request.
-    pub fn patch<U>(&self, url: U) -> ClientRequest
-    where
-        Uri: TryFrom<U>,
-        <Uri as TryFrom<U>>::Error: Into<HttpError>,
-    {
-        self.request(Method::PATCH, url)
-    }
-
-    /// Construct HTTP *DELETE* request.
-    pub fn delete<U>(&self, url: U) -> ClientRequest
-    where
-        Uri: TryFrom<U>,
-        <Uri as TryFrom<U>>::Error: Into<HttpError>,
-    {
-        self.request(Method::DELETE, url)
-    }
-
-    /// Construct HTTP *OPTIONS* request.
-    pub fn options<U>(&self, url: U) -> ClientRequest
-    where
-        Uri: TryFrom<U>,
-        <Uri as TryFrom<U>>::Error: Into<HttpError>,
-    {
-        self.request(Method::OPTIONS, url)
-    }
-
-    /// Initialize a WebSocket connection.
-    /// Returns a WebSocket connection builder.
-    pub fn ws<U>(&self, url: U) -> ws::WebsocketsRequest
-    where
-        Uri: TryFrom<U>,
-        <Uri as TryFrom<U>>::Error: Into<HttpError>,
-    {
-        let mut req = ws::WebsocketsRequest::new(url, self.0.clone());
-        for (key, value) in self.0.default_headers.iter() {
-            req.head.headers.insert(key.clone(), value.clone());
-        }
-        req
-    }
-
-    /// Get default HeaderMap of Client.
-    ///
-    /// Returns Some(&mut HeaderMap) when Client object is unique
-    /// (No other clone of client exists at the same time).
-    pub fn headers(&mut self) -> Option<&mut HeaderMap> {
-        Rc::get_mut(&mut self.0.default_headers)
-    }
-}
diff --git a/awc/src/request.rs b/awc/src/request.rs
index 3eb76e3f..8824dd08 100644
--- a/awc/src/request.rs
+++ b/awc/src/request.rs
@@ -12,10 +12,11 @@ use actix_http::{
 };
 
 use crate::{
+    client::ClientConfig,
     error::{FreezeRequestError, InvalidUrl},
     frozen::FrozenClientRequest,
     sender::{PrepForSendingError, RequestSender, SendClientRequest},
-    BoxError, ClientConfig,
+    BoxError,
 };
 
 #[cfg(feature = "cookies")]
@@ -249,23 +250,16 @@ impl ClientRequest {
     /// Set a cookie
     ///
     /// ```no_run
-    /// use awc::{cookie, Client};
+    /// use awc::{cookie::Cookie, Client};
     ///
     /// # #[actix_rt::main]
     /// # async fn main() {
-    /// let resp = Client::new().get("https://www.rust-lang.org")
-    ///     .cookie(
-    ///         awc::cookie::Cookie::build("name", "value")
-    ///             .domain("www.rust-lang.org")
-    ///             .path("/")
-    ///             .secure(true)
-    ///             .http_only(true)
-    ///             .finish(),
-    ///      )
-    ///      .send()
-    ///      .await;
+    /// let res = Client::new().get("https://httpbin.org/cookies")
+    ///     .cookie(Cookie::new("name", "value"))
+    ///     .send()
+    ///     .await;
     ///
-    /// println!("Response: {:?}", resp);
+    /// println!("Response: {:?}", res);
     /// # }
     /// ```
     #[cfg(feature = "cookies")]
diff --git a/awc/src/sender.rs b/awc/src/sender.rs
index 71d705d3..edf41163 100644
--- a/awc/src/sender.rs
+++ b/awc/src/sender.rs
@@ -24,8 +24,9 @@ use actix_http::{encoding::Decoder, header::ContentEncoding, Payload};
 
 use crate::{
     any_body::AnyBody,
+    client::ClientConfig,
     error::{FreezeRequestError, InvalidUrl, SendRequestError},
-    BoxError, ClientConfig, ClientResponse, ConnectRequest, ConnectResponse,
+    BoxError, ClientResponse, ConnectRequest, ConnectResponse,
 };
 
 #[derive(Debug, From)]
diff --git a/awc/src/ws.rs b/awc/src/ws.rs
index c63e2296..96f8cf89 100644
--- a/awc/src/ws.rs
+++ b/awc/src/ws.rs
@@ -31,18 +31,19 @@ use std::{convert::TryFrom, fmt, net::SocketAddr, str};
 use actix_codec::Framed;
 use actix_http::{ws, Payload, RequestHead};
 use actix_rt::time::timeout;
-use actix_service::Service;
+use actix_service::Service as _;
 
 pub use actix_http::ws::{CloseCode, CloseReason, Codec, Frame, Message};
 
 use crate::{
+    client::ClientConfig,
     connect::{BoxedSocket, ConnectRequest},
     error::{HttpError, InvalidUrl, SendRequestError, WsClientError},
     http::{
         header::{self, HeaderName, HeaderValue, TryIntoHeaderValue, AUTHORIZATION},
         ConnectionType, Method, StatusCode, Uri, Version,
     },
-    ClientConfig, ClientResponse,
+    ClientResponse,
 };
 
 #[cfg(feature = "cookies")]