Note: phiên bản Tiếng Việt của bài này ở link dưới.

https://duongnt.com/urchintai-api-vie

Perhaps most people who have tried to rent an apartment in Japan have heard about UR Chintai (UR賃貸住宅) with its many good perks like no key money, no guarantor needed, or deposit generally gets refunded. Recently, I realized that UR Chintai’s website is a dynamic one, and most of the contents in a page are loaded using JavaScript via API calls. What’s surprising to me is even though their API is public, there is scanty information about it on the Internet. The only mentions of it I can find is in this document on their homepage. However, by diving into their JavaScript files, I was able to learn quite a lot about that API.

Today, we will use their API to check the status of a property or a room. Then we will look at urchintai-client, a small Python package I wrote to make querying the API easier. You can find the source code for urchintai-client at the link below.

https://github.com/duongntbk/urchintai-client

We will use the following property URL and room URL in all of our examples. They do not have any special meaning, and I picked them randomly. Depending on when you read this article, that property and room may or may not be vacant, but that’s okay.

https://www.ur-net.go.jp/chintai/kanto/kanagawa/40_2600.html # <- This is our property URL
https://www.ur-net.go.jp/chintai/kanto/kanagawa/40_2600_room.html?JKSS=000000410 # <- And this is our room URL

Query information about a property

Diving in the code

The code to handle loading a property’s information is at this link. Keep in mind that if you open it using Chrome then the Japanese font will be messed up. You could still read the code itself without any problem, but I recommend using Firefox and setting the page encoding to Unicode for the best viewing experience.

We are interested in finding out if a particular property has any vacant room. So we need to look at the code to load the list of empty rooms in a property. That part starts from line 589.

return ur.api.ajax('bukken/detail/detail_bukken_room/', ajaxData)
    .done(function (data, status, jqXHR) {
        // bunch of code
    }).fail(function() {
        // bunch of code
    });

We can guess that we need to query bukken/detail/detail_bukken_room/ endpoint. To find the API’s root path, we will check the ur.api.ajax method, that method is defined in this file. From it, we can see that the API root is https://chintai.sumai.ur-net.go.jp/chintai/api/, and because there was no HTTP method provided, POST will be used. Next, we will find out what data we need to include in our request by looking at the ajaxData object.

var ajaxData = ur.api.bukken_detail.setPostData();

The setPostData method is defined at line 1124. We can see that they push a lot of data into ajaxData, but actually we only need the following six fields: shisya, danchi, shikibetu, orderByField, orderBySort and pageIndex (people with keen eyes might even realize that they mistakenly push pageIndex into ajaxData twice). Furthermore, the value of orderByField, orderBySort and pageIndex can all be set to 0 for our purpose, which leaves us with just three fields.

This is those three values are set.

ajaxData.push({name: 'shisya', value: ur.api.bukken_detail.param.shisya});
ajaxData.push({name: 'danchi', value: ur.api.bukken_detail.param.danchi});
ajaxData.push({ name: 'shikibetu', value: ur.api.bukken_detail.param.shikibetu });

ur.api.bukken_detail.param.XXX, in turn, are initialized at line 260 ~ 264, inside the ur.api.bukken_detail.initSearch method.

ur.api.bukken_detail.initSearch = function (shisya, danchi, shikibetu, life_designhouse, new_bukken_room) {
    //...
    // 支社
    ur.api.bukken_detail.param.shisya = shisya;
    // 団地
    ur.api.bukken_detail.param.danchi = danchi;
    // 識別
    ur.api.bukken_detail.param.shikibetu = shikibetu;
    //...
}

ur.api.bukken_detail.initSearch is not called anywhere inside this JavaScript file. But if you download the page using curl or a similar program with JavaScript turned off, you can find the following code.

<script type="text/JavaScript">
    $(function () {
        ur.cookie.setupBookmarkBukken();
        ur.cookie.saveHistoryBukken('40_2600');
        ur.api.bukken_detail.initSearch('40', '260', '0');
        ur.api.bukken_bukken.initSearch('40', '260', '0');
        $("a.td_underline_before:empty").parents(".cassettes_contact_box").remove();
        $("span.item_tel_number:empty").parents("span.button_tel_purple").remove();
    });
</script>

Remember that our property URL is https://www.ur-net.go.jp/chintai/kanto/kanagawa/40_2600.html and suddenly the three numbers 40, 260 and 0 become very familiar. We can then conclude that a property URL has this format: https://www.ur-net.go.jp/chintai/<area>/<prefecture>/AA_BBBC.html.

  • AA: shisya
  • BBB: danchi
  • C: shikibetu

Trying out the API

Putting everything together, we can request the list of empty rooms in a property like this.

Method: POST
Endpoint: https://chintai.sumai.ur-net.go.jp/chintai/api/bukken/detail/detail_bukken_room/
Form data: {
    'shisya': '40',
    'danchi': '260'
    'shikibetu': '0',
    'orderByField': '0',
    'orderBySort': '0',
    'pageIndex': '0',
}

The response as of this writing is below.

[
  {
    "pageIndex": "0",
    "rowMax": "5",
    "rowMaxSp": "3",
    "rowMaxNext": "10",
    "pageMax": "5",
    "allCount": "4",
    "block": "kanto",
    "tdfk": "kanagawa",
    "shisya": "40",
    "danchi": "260",
    "shikibetu": "0",
    "floorAll": "15階",
    "roomDetailLink": "/chintai/kanto/kanagawa/40_2600_room.html?JKSS=000000404",
    "roomDetailLinkSp": "/chintai/sp/kanto/kanagawa/40_2600_room.html?JKSS=000000404",
    "system": [
      {
        "制度_IMG": "btn_kinkyo.png",
        "制度名": "近居割",
        "制度HTML": "kinkyo"
      }
    ],
    "parking": null,
    "design": [
      {
        "デザイン_HTML": "renovation",
        "デザイン_IMG": "logo_renovation.png",
        "デザイン名": "リノベーション住宅"
      },
      {
        "デザイン_HTML": "premium",
        "デザイン_IMG": "logo_premium.png",
        "デザイン名": "プレミアムなお部屋"
      }
    ],
    "featureParam": [],
    "traffic": null,
    "place": null,
    "kanris": null,
    "kouzou": null,
    "soukosu": null,
    "id": "000000404",
    "year": null,
    "name": "404号室",
    "shikikin": "2か月",
    "requirement": "ナシ",
    "madori": "https://chintai.sumai.ur-net.go.jp/chintai/img_madori/40/40_260/40_260_0-00-0000_B5_RA_01_00011.gif",
    "rent": "101,800円",
    "rent_normal": "",
    "rent_normal_css": " dn",
    "commonfee": "4,100円",
    "commonfee_sp": null,
    "status": null,
    "type": "2DK",
    "floorspace": "45㎡",
    "floor": "4階",
    "urlDetail": null,
    "urlDetail_sp": null,
    "feature": null
  },
  {
    <OMITTED>
  },
  {
    <OMITTED>
  },
  {
    <OMITTED>
  }
]

This response contains a lot of information about each vacant room in this property. We can see there is a field called allCount, its value is the number of vacant rooms (4 as of the time I ran this query). There is also information about rent, room number, floor space,… Next, we will try to call this endpoint for another property which has no vacant room.

https://www.ur-net.go.jp/chintai/kanto/kanagawa/40_3600.html

The result is this.

null

From this, we can see that checking if a property has vacant rooms is very simple, just query bukken/detail/detail_bukken_room/ and see if the response is null or not.

Query information about a particular room

Diving in the code

The JavaScript code to handle loading a room’s information is at this link. The part we need to pay attention to starts at line 170.

ur.api.room_detail.getDataRoom = function () {
    var ajaxData = [
        {name: 'id', value: ur.api.room_detail.param.id},
        {name: 'shisya', value: ur.api.room_detail.param.shisya},
        {name: 'danchi', value: ur.api.room_detail.param.danchi},
        {name: 'shikibetu', value: ur.api.room_detail.param.shikibetu },
        {name: 'sp', value: (conf.isMobile()) ? '1' : '' }
    ];
    ur.api.ajax('bukken/detail/detail_room/', ajaxData)
        .done(function (data, status, jqXHR) {
            // bunch of code
        }).fail(function () {
            // bunch of code
        });
};

We can ignore the sp parameter for now, because it only sets a flag to aid mobile/PC display. It’s easy to see that ur.api.room_detail.param.XXX are initialized at line 144 ~ 159, inside the ur.api.room_detail.initSearch method. We already know that shisya, danchi and shikibetu are retrieved from the URL. And thanks to line 154, we can guess that id is parameter JKSS from the query string.

var id = ur.func.getParam('JKSS');

Trying out the API

Remember that our room URL is https://www.ur-net.go.jp/chintai/kanto/kanagawa/40_2600_room.html?JKSS=000000410, we will query the API as below.

Method: POST
Endpoint: https://chintai.sumai.ur-net.go.jp/chintai/api/bukken/detail/detail_room/
Form data: {
    'shisya': '40',
    'danchi': '260'
    'shikibetu': '0',
    'id': '000000410'
}

The response as of this writing is below.

[
  {
    "roomCatch1": "",
    "roomCatch2": "",
    "roomRead1": "",
    "roomRead2": "",
    "roomNm": "410号室",
    "rent_sp": "<span class=\"item_price\">135,600円</span><span class=\"item_commonfee\">(4,100円)</span>",
    "madoriYuka": "2LDK /63㎡",
    "madoriYuka_sp": "2LDK /63㎡",
    "floor_sp": "4階 /15階",
    "netLink": "https://sumai.ur-net.go.jp/chintai/s/otoiawase/juko.html?in=1040260000000410",
    "kariLink": "",
    "img": [
        <LINK TO ROOM's IMAGES>
    ],
    "movie": null,
    "otherRoom": [],
    "system": [
      {
        "制度_IMG": "btn_kinkyo.png",
        "制度名": "近居割",
        "制度HTML": "kinkyo"
      }
    ],
    "design": [
      {
        "デザイン_HTML": "renovation",
        "デザイン_IMG": "logo_renovation.png",
        "デザイン名": "リノベーション住宅"
      },
      {
        "デザイン_HTML": "premium",
        "デザイン_IMG": "logo_premium.png",
        "デザイン名": "プレミアムなお部屋"
      }
    ],
    "bookmark_key": "40_2600000000410",
    "parking": "<span>機械 空き台数:7台 料金:19,030円~21,120円<br></span><span class=\"item_text_parking-caution\">※ご契約時、駐車場敷金2か月が必要です。</span>",
    "facility": "エレベーター、エアコン、ドロップインコンロ、オートドアロック、防犯カメラ、プレイロット、BS、VDSL、アルコーブ、バス・トイレ別、洗面所独立、追い焚き、洗濯機置場(室内)、玄関収納、バルコニー",
    "biko": "<li>・2020年12月リノベーション済み(キッチン交換、洗面化粧台交換、床改修)</li>",
    "bikoUrLight": "",
    "featureParam": [],
    "mihoshu": "",
    "id": "000000410",
    "year": "32",
    "name": null,
    "shikikin": "2か月",
    "requirement": "ナシ",
    "madori": null,
    "rent": "<p class=\"price\">135,600円<span class=\"item_commonfee\">(4,100円)</span></p>",
    "rent_normal": null,
    "rent_normal_css": " dn",
    "commonfee": null,
    "commonfee_sp": null,
    "status": null,
    "type": null,
    "floorspace": null,
    "floor": "4階 /15階",
    "urlDetail": null,
    "urlDetail_sp": null,
    "feature": "最寄りの小中学校が徒歩10分以内、敷地内に公園あり、最寄りの公園が徒歩5分以内"
  }
]

What if we try to call the same endpoint for a non-vacant room, like this one?

https://www.ur-net.go.jp/chintai/kanto/kanagawa/40_2600_room.html?JKSS=000000411

The result is exactly what you would expect.

null

Thus checking if a room is vacant is also very simple, just query bukken/detail/detail_room/ and see if the response is null or not.

A note about room ID

From the last section, we know that the ID for room number 410 is 000000410. Because most UR Chintai property has more than nine floors but no property has more than 99 floors, we can reasonably expect that the last four digits in a room ID is the room number. But what about the leading six digits?

Let’s take a look at this property, it has three buildings, numbering 1, 2 and 3. The ID for room 204 in building 2 is 000020204. It’s unlikely for a property to have more than 99 buildings, so I guess the format of a room ID is AAABBCCCC.

  • AAA: I don’t know what this part means. For all rooms I can find, this part is 000.
  • BB: building number, if the property has only one building then this part is 00 instead of 01.
  • CCCC: room number.

Quick look of some other endpoints

Method: POST
Endpoint: https://chintai.sumai.ur-net.go.jp/chintai/api/bukken/detail/detail_bukken_bukken/
Form data: {
    'shisya': 'AA',
    'danchi': 'BBB'
    'shikibetu': 'C'
}

Returns the overview of a property, it has the following information.

  • Number of parking slots in a property and the monthly-price of a slot.
  • Surrounding area: kindergarten, library, public park,…
  • Building facilities: elevator, CATV, auto lock,…
Method: POST
Endpoint: https://chintai.sumai.ur-net.go.jp/chintai/api/bukken/detail/detail_bukken/
Form data: {
    'shisya': 'AA',
    'danchi': 'BBB'
    'shikibetu': 'C'
}

Returns pictures and videos of a property and its surrounding area. Each picture has two versions, a normal one and a small thumbnail.

Method: POST
Endpoint: https://chintai.sumai.ur-net.go.jp/chintai/api/bukken/detail/detail_bukken_design/
Form data: {
    'bukkenid': 'AA_BBB' # For our example, the bukkenid is 40_260. Don't know why this one is different from the rest
}

Returns the following information about a property.

  • Address.
  • The nearest train station.
  • Total number of rooms.
  • The year when UR Chintai started managing this property.
  • Type of building (concrete, wood,…).
Method: POST
Endpoint: https://chintai.sumai.ur-net.go.jp/chintai/api/bukken/detail/detail_bukken_tenpo/
Form data: {
    'shisya': 'AA',
    'danchi': 'BBB'
    'shikibetu': 'C'
}

Returns information about the branch that manages a property. It has the phone number, address, holiday, open time,… of that branch. This information will come in handy when you want to apply for a room in that property.

Method: POST
Endpoint: https://chintai.sumai.ur-net.go.jp/chintai/api/bukken/detail/bukken_main/
Form data: {
    'shisya': 'AA',
    'danchi': 'BBB'
    'shikibetu': 'C'
}

This endpoint seems to be a simplified version of detail_bukken_bukken. They return mostly the same information but bukken/search/bukken_main is limited to the subset of vacant room(s).

Introducing urchintai-client

Remembering what endpoint to call with what data can get tiring quickly. Because of that, I wrote a small Python package called urchintai-client to make querying UR Chintai API easier. You can read more about it on GitHub.

https://github.com/duongntbk/urchintai-client

Here, I will only introduce one use case, checking if a property has any vacant room using its URL. Assuming that you’ve already installed urchintai-client, run the following script in Python terminal.

import asyncio

from urchintai_client.session_manager import SessionManager
from urchintai_client.request_sender import RequestSender
from urchintai_client.ur_client import UrClient

sender = RequestSender(SessionManager.GetSession())
client = UrClient(sender)

url = 'https://www.ur-net.go.jp/chintai/kanto/kanagawa/40_2600.html'
loop = asyncio.get_event_loop()
is_vacant = loop.run_until_complete(client.is_property_vacant(url))
print(f'Property has vacant room(s): {is_vacant}')

loop.run_until_complete(SessionManager.CloseSession()) # Don't forgot to close the session

At the time of this writing, the script above prints the following message to console.

Property has vacant room(s): True

Conclusion

Armed with the knowledge about UR Chintai API, we could easily add more functionalities to urchintai-client. With the correct combination of calls, it is possible to programmatically retrieve any information you want from their system. Maybe we can use this to create a bot to periodically check the status of a property or a room and send notification when a new room becomes available.

A software developer from Vietnam and is currently living in Japan.

One Thought on “Use API to query information from UR Chintai”

Leave a Reply