David Amunga

Software Maker·Frontend / Mobile·Nairobi, Kenya
  • Senior Frontend Engineer at Piedmont Global
  • 8+ years building mobile & web applications
David Amunga
All posts
Blog

Reverse Engineering the KPLC API using Puppeteer for fun

17 Dec 2022

How i was able to reverse engineer the KPLC API to derive some insights

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

Introduction

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.

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.

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,
});

Navigation

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.

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.

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.

Conclusion

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.