The wrappers are simple request and response objects which you can subclass to do whatever you want them to do.


When a page is requested, you create a request object that contains metadata about the request. You can then pass the request object as argument to the view functions or use it inside the application callable.

from werkzeug import BaseRequest

class Request(BaseRequest):
    charset = 'utf-8'

def application(environ, start_response):
    req = Request(environ)
    start_response('200 OK', [('Content-Type', 'text/plain')])
    yield 'Hello %s!' % req.args.get('subject', 'World')

All incoming data is decoded into unicode objects automatically so you don't have to care about that.

The request object will store itself as 'werkzeug.request' in the WSGI environment.

Class Methods

from_values(path, base_url, query_string, **options)

Create a new request object based on the values provided. If environ is given missing values are filled from there. This method is useful for small scripts when you need to simulate a request from an url. Do not use this method for unittesting, there is a full featured client object in werkzeug.test that allows to create multipart requests etc.

This accepts the same options as the create_environ function from the utils module and additionally an environ parameter that can contain values which will override the values from dict returned by create_environ.

Additionally a dict passed to query_string will be encoded in the request class charset.


This method is called whenever the form data parser needs a read and write stream for the incoming data. Per default this returns a stream that points to a temporary file. If you want to override this method keep in mind that the stream object returned must support read and write operations.


The current path requested, relative to the position where the WSGI application is mounted (PATH_INFO). It will contain a leading slash and will be at least a string with a single slash when accessing the URL root.
The root path for the script (SCRIPT_NAME). Does not contain a trailing slash.
The full URL for the current request.
The current full URL without the query string.
The current URL up to the script root.
The current URL for the host.
The current hostname, without scheme.
True if this is an https request.
The request method. GET, POST etc.
A dictionary-like object containing all given HTTP GET parameters. See the MultiDict documentation in the utils section.

A dictionary-like object containing all given HTTP POST parameters. See the MultiDict documentation in the utils section.

This dict does not contain uploaded files, see files therefore.

An immutable dictionary-like object containing both the args and form values. See the CombinedMultiDict documentation in the utils section.
A dictionary with the submitted cookie values.

A dictionary-like object containing all uploaded files. Each key in files is the name from the <input type="file" name="" />. Each value in files is a werkzeug FieldStorage object with the following members:

  • filename - The name of the uploaded file, as a Python string.
  • type - The content type of the uploaded file.
  • data - The raw content of the uploaded file.
  • read() - reads from the stream

Note that files will only contain data if the request method was POST and the <form> that posted to the request had enctype="multipart/form-data". Otherwise, it will be empty.

See the MultiDict documentation in the utils section for more details about the used data structure.

The WSGI environment used to create the request object.
The buffered stream with incoming data from the webbrowser if the submitted data was not multipart or urlencoded form data.
The input stream provided by the client. Used internally by the form data parser. Reading from this stream must never be mixed with accessing stream, data, files, or form because then it is not guaranteed that more data is requested from the client than expected. Never read beyond environ['CONTENT_LENGTH'].
Accessing this the first time reads the whole stream and stores it. Keep in mind that this does not read the whole wsgi input stream like django does.
List of mimetypes this client supports.
List of charsets this client supports.
List of encodings this client accepts. Do not mix this up with accept_charset which contains character encodings whereas accept_encodings contains compression encodings such as gzip.
List of langauges this client accepts.
The remote address for the user that created this request. If the class variable is_behind_proxy is set to True (either by subclassing the process or overriding this variable on the instance) it will try to get the value from the X_HTTP_FORWARDED_FOR header. Keep in mind that this is disabled by default because unless you are really behind a proxy this is a security problem.
If you are behind a proxy server this will list all the ips that take place in the request. The end user ip is the first one in the list, the last proxy server is the last item in the list. This also works if the is_behind_proxy class variable is set to False.


The response object is the opposite of the request object. It wraps the start_response function. In order to keep the interface extensible it has the same signature as a normal WSGI callable, thus it takes the environ as first argument.

You can use that as replacement for start_response and returning an iterable:

from werkzeug import BaseResponse

class Response(BaseResponse):
    charset = 'utf-8'

def application(environ, start_response):
    resp = Response(u'<h1>Hello World</h1>', mimetype='text/html')
    return resp(environ, start_response)

Ideally all data is stored internally as unicode. Bytestrings passed to the object will be returned unchanged in order to support binary data.

The following members exist:

Override this to change the internal charset. This is always a very good idea because the default is ascii.
The used mimetype if no other is defined. Default is text/plain.


There are multiple ways to use the response object. The constructor accepts the following arguments:


Can be an iterator or a string or None. If it's an iterator, it should return strings (unicode/str), and those strings will be joined together to form the content of the response.

If you pass it an iterable it's used for direct data submission (streaming):

def my_view(...):
    def wrapped():
        for item in range(100):
            yield str(item) + ' '
    return Response(wrapped, mimetype='text/html')

This will then take 10 seconds to submit all data but the browser will render after each iteration.

The status number of the response. Defaults to 200. Note that those can either be strings or integers.
Either None, a list or dict of headers or a werkzeug Headers instance. See the Headers documentation in the utils section.
The mimetype of the response. If there is no charset definition in that mimetype and the mimetype is a text mimetype it will automatically append the charset of the response object. The default mimetype is 'text/plain'.
Most of the time mimetype and content_type work the same. The difference affects only 'text' mimetypes. If the mimetype passed with mimetype is a mimetype starting with text/ it gets a charset parameter added with the charset of the response object. In constrast the content_type parameter is always added as header unmodified.

Class Methods

from_app(app, environ, buffered=False)
Create a new response object from an application output. This works best if you pass it an application that returns a generator all the time. Sometimes applications may use the write() callable returned by the start_response function. This tries to resolve such edge cases automatically. But if you don't get the expected output you should set buffered to True which enforces buffering.


write(data) / writelines(lines)

If the response object was created not by passing it an iterable but either a string, list or nothing it will be created in file-like mode.

This means that you can write data to the internal buffer, it doesn't mean that you directly pass the data to the webserver, if you want to do that you should use a generator and pass that to the response object.

set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None)

Sets a cookie. The parameters are the same as in the cookie Morsel object in the Python standard library but it accepts unicode data too:

  • max_age should be a number of seconds, or None (default) if the

    cookie should last only as long as the client’s browser session.

  • expires should be a datetime object or unix timestamp.

  • Use domain if you want to set a cross-domain cookie. For example, domain=".example.com" will set a cookie that is readable by the domain www.example.com, foo.example.com etc. Otherwise, a cookie will only be readable by the domain that set it.

  • path limits the cookie to a given path, per default it will span the whole domain.

delete_cookie(key, path='/', domain=None)
Deletes the cookie with the given key. Fails silently if the key doesn’t exist.
Iterate over the response encoded with the encoding specified. If no encoding is given the encoding from the class is used. Note that this does not encode data that is already encoded into a bytestring.
This is automatically called right before the response is started and should fix common mistakes in headers. For example location headers are joined with the root URL here.
Close the wrapped response object if there is anything to close.


A Headers instance from the utils module that represents the headers set currently.
The complete header list as read only copy in the charset of the response.
The current response object. This always is an iterable.
The string representation of the request body. Whenever you access this property the request iterable is encoded and flattened. This can lead to unwanted behavior if you stream big data.
The status string. For example '200 OK'.
The status code. For example 200.