Reverse Engineering the KPLC API using Puppeteer for fun

Reverse Engineering the KPLC API using Puppeteer for fun

How i was able to reverse engineer the KPLC API to derive some insights
2nd Posted URL
Action Items
Next Action Date
Dec 7, 2022
Posted URL
Published Date
Dec 17, 2022
kplc,electricity tracker,api,puppeteer,express,nextjs,kenya,reverse engineer
This is an article highlighting how i stumbled onto a use case on expanding upon the KPLC API to build a better reporting tool for consumers.
For more on how I came up with this idea. Check out How I built an Electricity Tracker for fun and (not) profit


I discovered there was part of the Self Service Portal doesn’t show the full results on the UI. Being a curious developer i peeped onto the network tab and found out that they are returning more transactional data than what was shown. I decided that it would be a fun try to use the API to get the data directly.

Inspecting the KPLC API

If you Inspect the Network tab on your Devtools as you make a request you’ll discover the Request URL that is https://selfservice.kplc.co.ke/api with your serial number meter as the query param you’ll be able to get a result.
notion image
The Request headers include a bearer token which when you check out using Postman you’ll find quite the bit of data included in it.
notion image
I wasn’t really aware of the filters on how far back the data is fetched from but it was enough to work with ~6 months. I decided to use Puppeteer to build out the Automation.

Why I chose Puppeteer

Puppeteer is a Node.js library that provides a high level API to control Chromium. It runs on headless mode by default. The KPLC API is currently authenticated using a Bearer token. It would be ideal to use browser automation since we’ll be quering the API directly from the UI like a normal user would do so. Despite this being slower at the time i believed it would be the safest way of consuming the API without it being perceived as abuse.

Starting off

To start off with Puppeteer you’d have to launch the browser in headless mode so that you can navigate to the Bill / Meter Query Page
// Start Puppeteer const browser = await puppeteer.launch({ headless: true }); // Open New Page const page = await browser.newPage(); // Navigate to KPLC Self Service Portal await page.goto(KPLC_URL, { waitUntil: 'load', timeout: 0, });


To begin navigation you would need to wait until all the elements have loaded on the page. You can decide to select the any selector id to validate this
await page.waitForSelector('#button-{ID}');
We intend to navigate to the Bill/Meter Query link.
notion image
You can initiate a click on the link using
await page.click('#{LINK_ID}');

Inputting the Meter Data at the Query Page

At the query page you’ll arrive at a form where you can input the data.
notion image
Using Puppeteer this will go like
//Select Meter Number Option await page.click('#{RADIO_BUTTON_ID}'); //Type Meter number await page.type('#{TEXT_FIELD_ID}', YOUR_METER_NUMBER); // Submitting the Request by clicking the search button await page.click('#{SEARCH_BUTTON_ID}');

Getting the Response Data from DevTools

You can listen in on the page response data if the url includes the KPLC_URL to get the json directly.
// Listen on network response page.on('response', async (response) => { if ( response .url() .includes(KPLC_URL) ) { const json = await response.json(); // WOOHOO ! GOT THE DATA } });

Data Cleanup

You’ll notice the data could contain some unnecessary/sensitive info (name,servicePointNo) so you can build out your own model of what you intend to get back from your API.


After discovering the above i was able to validate that Puppeteer is a really helpful tool for browser automation and in future plan to use the same for hobby projects rather than E2E Testing for web applications.

Last edited on Tue Jun 06 2023

Hey there 👋

Was anything I wrote confusing, outdated, or incorrect? Please let me know! Just write a few words below and I'll be sure to amend this post with your suggestions.