Skip to content


Routes define what happens when your client connects to a certain URL.


CROW_ROUTE(app, url)
Can be replaced with app.route<crow::black_magick::get_parameter_tag(url)>(url) or app.route_dynamic(url) if you're using VS2013 or want runtime url evaluation. Although this usage is NOT recommended.


Which app class to assign the route to.

Path (URL)

Which relative path is assigned to the route.
Using /hello means the client will need to access in order to access the route.
A path can have parameters, for example /hello/<int> will allow a client to input an int into the url which will be in the handler (something like
Parameters can be <int>, <uint>, <double>, <string>, or <path>.
It's worth nothing that the parameters also need to be defined in the handler, an example of using parameters would be to add 2 numbers based on input:

CROW_ROUTE(app, "/add/<int>/<int>")
([](int a, int b)
    return std::to_string(a+b);
you can see the first <int> is defined as a and the second as b. If you were to run this and call, the result would be a page with 3. Exciting!


You can change the HTTP methods the route uses from just the default GET by using method(), your route macro should look like CROW_ROUTE(app, "/add/<int>/<int>").methods(crow::HTTPMethod::GET, crow::HTTPMethod::PATCH) or CROW_ROUTE(app, "/add/<int>/<int>").methods("GET"_method, "PATCH"_method).


Crow handles HEAD and OPTIONS methods automatically. So adding those to your handler has no effect.


Basically a piece of code that gets executed whenever the client calls the associated route, usually in the form of a lambda expression. It can be as simple as ([](){return "Hello World"}).


Handlers can also use information from the request by adding it as a parameter ([](const crow::request& req){...}).

You can also access the url parameters in the handler using req.url_params.get("param_name");. If the parameter doesn't exist, nullptr is returned.

For more information on crow::request go here.


Crow also provides the ability to define a response in the parameters by using ([](crow::response& res){...}).

Please note that in order to return a response defined as a parameter you'll need to use res.end();.

Alternatively, you can define the response in the body and return it (([](){return crow::response()})).

For more information on crow::response go here.

Return statement

A crow::response is very strictly tied to a route. If you can have something in a response constructor, you can return it in a handler.

The main return type is std::string. although you could also return a crow::json::wvalue or crow::multipart::message directly.

For more information on the specific constructors for a crow::response go here.

Returning custom classes

If you have your own class you want to return (without converting it to string and returning that), you can use the crow::returnable class.
to use the returnable class, you only need your class to publicly extend crow::returnable, add a dump() method that returns your class as an std::string, and add a constructor that has a Content-Type header as a string argument.

your class should look like the following:

class a : public crow::returnable 
    a() : returnable("text/plain"){};


    std::string dump() override
        return this.as_string();

Catchall routes

By default, any request that Crow can't find a route for will return a simple 404 response. You can change that to return a default route using the CROW_CATCHALL_ROUTE(app) macro. Defining it is identical to a normal route, even when it comes to the const crow::request& and crow::response& parameters being optional.