Russian Railway (РЖД) API Documentation 🚂
For a long time, I’ve been interested in air travel and using my programming skills to find interesting routes, cheap fares and mileage optimised routings. However, after reading the blogs such as The Man in Seat Sixty-One I’ve also beginning to get more interested in overland travel, specifically train and bus journeys.
While there are numerous interesting train routes out there, one of the most famous ones is undoubtedly the Trans-Siberian Railway. With over 9289 km or 5772 Miles it’s the world’s longest railway line. What I found particularly interesting is that you can connect even further, basically allowing to routings from Central Europe to Hanoi, Vietnam or Beijing, China.
When trying to plan your own trip on “Transsib” you’ll soon notice that it can soon become a very time-intensive hobby, as some trains don’t always run, have no availability (90 day booking period) or are not necessarily arriving or departing at the right time. To make things worse, the РЖД website used to be not the easiest to navigate and at times buggy. I, therefore, did a little bit of reverse engineering and searched for ways to automate the search. As a result, I documented the RZD API in Postman, to allow easy implementation in a language of your choice. The documentation can be found on documenter.
Which data can be retrieved from РЖД API?
I was able to retrieve the following pieces of information from the website:
- Get the train-stations for a specific train number on a certain date:
- Search train stations based on a query string
- Distance between the stations, waiting times as well as arrival and departure times
How the RZD API works (high-level)
The RZD API has a request scheme that is fairly easy to grasp. For each task, there is an endpoint that is usually defined by a parameter called layer_id that takes certain parameters (see the specifics of each endpoint below). If the request was valid, the API would respond with a
json containing a RID. The response willJSONk similar to this one:
Alongside the RID, the Server will also yield back a
SET-Cookie header that has JSESSIONID Cookie. This cookie has to be added to any future requests. Unlike the
RID, the Cookie JSESSIONID Cookie doesn’t change during every request.
The actual data is then fetched via a
POST request from a single endpoint containing the previously retrieved
Please see the Postman documentation for a full list of parameters and options.
Little Python Example
Let’s assume we want to search available a one-way third-class ticket from Saint Petersburg to Moscow and we are willing to transfer. The matching Python request could look like this:
The response, which we get back, will look something like this (notice the RID):
Along with the JSON response, we also retrieved two cookies:
We can now use these to retrieve the actual data. To do so, I will simply reuse the session object, but this time make a
POST request containing the
Update: I have added a delay of more than 60 seconds prior to executing the second request. According to some feedback of a lovely reader, this is necessary to get the desired response.
If we piece it together, the whole code will then look like this:
As a response, you should get a neat
json with all the information you desire.
I hope my RZD API documentation is also useful for your next train journey.