diff --git a/README.md b/README.md
index 2f72508690a43e4d3944d1cea1f4f1ae6a67f6dd..ad1624ba16c342789615b1e504e23cab304aba7a 100644
--- a/README.md
+++ b/README.md
@@ -535,6 +535,19 @@ You can control the upstream endpoint via the --upstream-url option. Both http a
 
 Assuming the *--enable-metrics* has been set, a Prometheus endpoint can be found on */oauth/metrics*; at present the only metric being exposed is a counter per http code.
 
+### Limitations
+
+Keep in mind [browser cookie limits](http://browsercookielimits.squawky.net/), if you use access or
+refresh tokens in the browser cookie. Keycloak-proxy divides cookie automatically if your cookie
+is longer than 4093 bytes. Real size of the cookie depends on the content of the issued access token. 
+Also, encryption might add additional bytes to the cookie size. If you have large cookies (>200 KB),
+you might reach browser cookie limits. 
+
+All cookies are part of the header request, so you might find a problem with the max headers size 
+limits in your infrastructure (some load balancers have very low this value, such as 8 KB). Be 
+sure that all network devices have sufficient header size limits. Otherwise, your users won't be 
+able to obtain access token.
+
 ### **Contribution Guidelines**
 ----
 
diff --git a/cookies.go b/cookies.go
index a852d1b39d62f94cff4a734d704a4ef3a811f2c3..a257a126f7c70dcb6055c6a5c815f4126684c8a9 100644
--- a/cookies.go
+++ b/cookies.go
@@ -17,6 +17,7 @@ package main
 
 import (
 	"net/http"
+	"strconv"
 	"strings"
 	"time"
 )
@@ -45,12 +46,42 @@ func (r *oauthProxy) dropCookie(w http.ResponseWriter, host, name, value string,
 
 // dropAccessTokenCookie drops a access token cookie into the response
 func (r *oauthProxy) dropAccessTokenCookie(req *http.Request, w http.ResponseWriter, value string, duration time.Duration) {
-	r.dropCookie(w, req.Host, r.config.CookieAccessName, value, duration)
+	// also cookie name is included in the cookie length; cookie name suffix "-xxx"
+	maxCookieLenght := 4089 - len(r.config.CookieAccessName)
+
+	if len(value) <= maxCookieLenght {
+		r.dropCookie(w, req.Host, r.config.CookieAccessName, value, duration)
+	} else {
+		// write divided cookies because payload is too long for single cookie
+		r.dropCookie(w, req.Host, r.config.CookieAccessName, value[0:maxCookieLenght], duration)
+		for i := maxCookieLenght; i < len(value); i += maxCookieLenght {
+			end := i + maxCookieLenght
+			if end > len(value) {
+				end = len(value)
+			}
+			r.dropCookie(w, req.Host, r.config.CookieAccessName+"-"+strconv.Itoa(i/maxCookieLenght), value[i:end], duration)
+		}
+	}
 }
 
 // dropRefreshTokenCookie drops a refresh token cookie into the response
 func (r *oauthProxy) dropRefreshTokenCookie(req *http.Request, w http.ResponseWriter, value string, duration time.Duration) {
-	r.dropCookie(w, req.Host, r.config.CookieRefreshName, value, duration)
+	// also cookie name is included in the cookie length; cookie name suffix "-xxx"
+	maxCookieLenght := 4089 - len(r.config.CookieRefreshName)
+
+	if len(value) <= maxCookieLenght {
+		r.dropCookie(w, req.Host, r.config.CookieRefreshName, value, duration)
+	} else {
+		// write divided cookies because payload is too long for single cookie
+		r.dropCookie(w, req.Host, r.config.CookieRefreshName, value[0:maxCookieLenght], duration)
+		for i := maxCookieLenght; i < len(value); i += maxCookieLenght {
+			end := i + maxCookieLenght
+			if end > len(value) {
+				end = len(value)
+			}
+			r.dropCookie(w, req.Host, r.config.CookieRefreshName+"-"+strconv.Itoa(i/maxCookieLenght), value[i:end], duration)
+		}
+	}
 }
 
 // clearAllCookies is just a helper function for the below
@@ -62,9 +93,29 @@ func (r *oauthProxy) clearAllCookies(req *http.Request, w http.ResponseWriter) {
 // clearRefreshSessionCookie clears the session cookie
 func (r *oauthProxy) clearRefreshTokenCookie(req *http.Request, w http.ResponseWriter) {
 	r.dropCookie(w, req.Host, r.config.CookieRefreshName, "", -10*time.Hour)
+
+	// clear divided cookies
+	for i := 1; i < 600; i++ {
+		var _, err = req.Cookie(r.config.CookieRefreshName + "-" + strconv.Itoa(i))
+		if err == nil {
+			r.dropCookie(w, req.Host, r.config.CookieRefreshName+"-"+strconv.Itoa(i), "", -10*time.Hour)
+		} else {
+			break
+		}
+	}
 }
 
 // clearAccessTokenCookie clears the session cookie
 func (r *oauthProxy) clearAccessTokenCookie(req *http.Request, w http.ResponseWriter) {
 	r.dropCookie(w, req.Host, r.config.CookieAccessName, "", -10*time.Hour)
+
+	// clear divided cookies
+	for i := 1; i < len(req.Cookies()); i++ {
+		var _, err = req.Cookie(r.config.CookieAccessName + "-" + strconv.Itoa(i))
+		if err == nil {
+			r.dropCookie(w, req.Host, r.config.CookieAccessName+"-"+strconv.Itoa(i), "", -10*time.Hour)
+		} else {
+			break
+		}
+	}
 }
diff --git a/session.go b/session.go
index 6bb11f90ac49b2cd1a228824211dec7118416e1d..bd47ff9ef85798e36f803ef3a5eac3c85d6ceef8 100644
--- a/session.go
+++ b/session.go
@@ -16,7 +16,9 @@ limitations under the License.
 package main
 
 import (
+	"bytes"
 	"net/http"
+	"strconv"
 	"strings"
 
 	"github.com/gambol99/go-oidc/jose"
@@ -100,8 +102,25 @@ func getTokenInBearer(req *http.Request) (string, error) {
 
 // getTokenInCookie retrieves the access token from the request cookies
 func getTokenInCookie(req *http.Request, name string) (string, error) {
+	var token bytes.Buffer
+
 	if cookie := findCookie(name, req.Cookies()); cookie != nil {
-		return cookie.Value, nil
+		token.WriteString(cookie.Value)
+	}
+
+	// add also divided cookies
+	for i := 1; i < 600; i++ {
+		cookie := findCookie(name+"-"+strconv.Itoa(i), req.Cookies())
+		if cookie == nil {
+			break
+		} else {
+			token.WriteString(cookie.Value)
+		}
 	}
-	return "", ErrSessionNotFound
+
+	if token.Len() == 0 {
+		return "", ErrSessionNotFound
+	}
+
+	return token.String(), nil
 }