Mctaba Labs logo
BootcampData ScienceThe WhiteboardProjectsEventsMasterclassesWebinarsLearn
Book CallApply

500+ developers already in the community

Get answers, find accountability partners, and stay ahead

Join Discord →
Mctaba Labs logo

Educating 1 million students in tech by 2030.

Programs

  • Coding Bootcamp in Nairobi
  • Data Science to AI Engineering
  • HighSchool Graduates Launchpad
  • AI & Business Automation
  • Corporate Training
  • Kids & Teens
  • McTaba Story & Mission
  • Full-Stack Curriculum
  • Course Pricing & Plans
  • Frequently Asked Questions

Resources

  • Join Discord Community
  • Tech Events in Nairobi
  • Masterclasses
  • Free Resources
  • Learn
  • Data Science Guides
  • African Payments Reference
  • Campus
  • Africa Tech Talent Report
  • Partner With Us
  • Start a Project
  • Software & AI Studio
  • Our Work
  • Outcomes

Contact Us

  • 124 Manyani East Road, Lavington, Nairobi
  • +254727795603
  • Book a Discovery Call

Office Hours:

Mon-Fri: 9am - 2pm EAT

Sat: 10am - 12pm EAT

© 2026 Mctaba Labs - A product of Edtech Industries. All rights reserved.

Privacy PolicyTerms of ServiceRefund Policy
  1. Learn
  2. Data Science in Kenya
  3. Analyse Your M-Pesa Statement in Python
Bonaventure OgetoBy Bonaventure Ogeto|Updated November 3, 2026

Last checked 3 November 2026

Analyse Your M-Pesa Statement in Python

Request the full statement, open the password-protected PDF with pdfplumber, load the table rows into pandas, drop failed and repeated header rows, turn the money columns into numbers, label each row with keyword rules, then group by category and plot. The code below does all of it on made-up rows.

In this article

  1. 1. Get your statement and open the lock
  2. 2. Read the PDF into a table
  3. 3. Clean it and sort spending into categories
  4. 4. Chart one month

Get your statement and open the lock

McTaba runs coding and data bootcamps in Kenya. This guide is written to be useful whether or not you ever join one.

Your M-Pesa statement is the best practice dataset you already own. Every shilling you sent, paid or received is a row. This tutorial is one project in our data science career map for Kenya.

Request a full statement through the M-Pesa menu on *234# or the Safaricom self-care site. The statement arrives by email as a PDF (Kenyans.co.ke guide, checked on 3 November 2026).

The password is where guides disagree. The Kenyans.co.ke guide says it is the ID document registered on your line. A People Daily report on Safaricom's explanation says each request gets its own password by SMS (checked on 3 November 2026). Try the SMS code first, then your ID number.

Open your own PDF before writing code. Look for these seven columns: receipt number, completion time, details, status, paid in, withdrawn and balance. Names and order can change, so match them to what you see.

A note on privacy

The file holds your name, your phone number and the numbers of everyone you paid. Keep it on your laptop. Never upload it to a free online converter. Never commit it to GitHub: add *.pdf to .gitignore. If you share a chart, share the totals, not the rows.

Read the PDF into a table

Install the tools with pip install pdfplumber pandas matplotlib. The code below reads every table on every page. The rows in this tutorial are made up, so your totals will differ.

import pdfplumber
import pandas as pd

PASSWORD = "12345678"  # the SMS code, or your ID number
rows = []
with pdfplumber.open("statement.pdf", password=PASSWORD) as pdf:
    for page in pdf.pages:
        for table in page.extract_tables():
            rows.extend(table)

cols = ["receipt", "time", "details", "status",
        "paid_in", "withdrawn", "balance"]
df = pd.DataFrame(rows, columns=cols)
print(df.head())

If extract_tables() returns nothing, your statement may not have ruled lines. Try page.extract_table(table_settings={"vertical_strategy": "text", "horizontal_strategy": "text"}), or the camelot library, which has a "stream" mode for tables without lines.

Problem you will seeCauseFix
Header words inside the dataThe header repeats on each pageDrop rows where receipt equals the header text
Amounts read as textCommas, such as 20,000.00Strip commas, then pd.to_numeric
Withdrawals look negativeThe withdrawn column carries a minus signUse abs() on the column
Money that never movedFailed and reversed rowsKeep only completed rows

These are the problems we ran into on a made-up statement. Real statements may add more, so print df["status"].unique() and read what is there.

The same cleaning steps are covered in more depth in our pandas tutorial on a Nairobi shop's sales. Our Data Science to AI Engineering programme covers pandas in phase 2.

Get weekly developer tips

Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.

No spam. Unsubscribe anytime.

Clean it and sort spending into categories

df = df[df["receipt"] != "Receipt No."]
df = df[df["status"].str.upper() == "COMPLETED"]
df["time"] = pd.to_datetime(df["time"])
for c in ["paid_in", "withdrawn", "balance"]:
    df[c] = pd.to_numeric(
        df[c].str.replace(",", ""), errors="coerce"
    ).fillna(0)
df["spent"] = df["withdrawn"].abs()

RULES = {
    "Airtime and data": ["SAFARICOM", "AIRTIME", "BUNDLES"],
    "Electricity": ["KPLC"],
    "Groceries": ["NAIVAS", "QUICKMART", "CARREFOUR"],
    "Eating out": ["JAVA", "KFC", "CAFE"],
    "Cash out": ["WITHDRAWAL"],
    "Sent to people": ["CUSTOMER TRANSFER"],
}

def categorise(text):
    text = text.upper()
    for name, words in RULES.items():
        if any(w in text for w in words):
            return name
    return "Other"

df["category"] = df["details"].apply(categorise)

The details column is free text: a till name, a paybill number, a person's name. A keyword table is a fair start. Print df[df.category == "Other"]["details"] and add words until "Other" is small.

Rules go first-match-wins, so put the narrow ones above the wide ones. "SAFARICOM" sits above "CUSTOMER TRANSFER" for a reason: a bundle purchase must not land in "Sent to people".

Chart one month

import matplotlib.pyplot as plt

spend = df[df["spent"] > 0]
october = spend[(spend["time"] >= "2026-10-01")
                & (spend["time"] < "2026-11-01")]
by_cat = (october.groupby("category")["spent"]
          .sum().sort_values())
print(by_cat)

by_cat.plot.barh(color="#2a6f4e")
plt.xlabel("KES spent")
plt.title("Spending by category, October")
plt.tight_layout()
plt.savefig("october.png")

A sorted horizontal bar reads faster than a pie. Look at the longest bar first and ask whether it matches how you think you spend. Most people are surprised by "Cash out" and "Sent to people".

Next, try a daily line for paid_in against spent with october.groupby(october["time"].dt.date). Month-end dips show up quickly. Turning that into a story for someone else is the skill in our data storytelling guide.

Where to take it

The same table can feed a budget alert, or a score of how steadily money comes in. The chama version of that idea is in our chama credit score tutorial. If you handle other people's statements, read how to anonymise personal data in Kenya first.

Want this skill with a mentor and a capstone? Our Data Science to AI Engineering programme starts 11 January 2027 at KES 140,000, with 5 months full time or 8 months part time.

Key Takeaways

  • ✓Open your own PDF first and match the code to the column names you see.
  • ✓Clean before you count: drop repeated headers, failed rows and commas in amounts.
  • ✓A keyword table is a fair first categoriser. Shrink the Other bucket by reading it.
  • ✓Treat the statement as private: laptop only, never in GitHub.

Frequently Asked Questions

What is the password for the M-Pesa statement PDF?
Sources differ. One guide says it is the ID document registered on your line. A People Daily report says Safaricom sends a fresh password by SMS with each request. Try the SMS code first, then your ID number.
Can I convert an M-Pesa statement PDF to Excel?
Yes. Read the table with pdfplumber, build a pandas DataFrame, then call df.to_excel("statement.xlsx"). You need the openpyxl package installed for that last step.
Is it safe to upload my statement to an online converter?
No. The file holds your phone number and the numbers of people you paid. Process it on your own laptop and keep it out of GitHub.
Why do some rows end up in the Other category?
The details column is free text, so the keyword table will miss some names. Print the Other rows, add the missing words to the rules and run it again.

Learn data science on African data

KES 140,000

Data Science to AI Engineering: 5 months full time or 8 months part time, hybrid in Nairobi. Fraud, credit and M-Pesa data from Week 1, and every model deployed. Starts 11 January 2027.

See the Data Science programme

Need it live by next month? Our studio builds it

Related guides

  • From Excel to Python: A Migration Plan for Analysts
  • Excel and Power BI or Python? What Kenyan Employers Ask For
  • Forecast a Shop's Stock from Till Data

Keep reading

Pandas Tutorial Using a Nairobi Shop's Sales Data

A pandas tutorial on a kiosk sales file instead of the Titanic: load it, clean it, rank products and find the slow days.

Read more

Build a Credit Score for a Chama from Contribution Records

Score members of a chama from their contribution history: first with points anyone can read, then with logistic regression, and with consent in mind.

Read more

Data Storytelling: Turning a Chart into a Decision

A chart is not the finish line. This guide shows the one-page memo, a simple way to pick a chart, and a before and after on made-up shop data.

Read more

Kenya's Data Protection Act for Data Scientists

The Act in plain words for people who handle customer data, then a pandas walk-through: salted hashes for phone numbers, generalised fields and a k-anonymity check.

Read more

Explore related topics

Breaking Into Tech

Practical, no-nonsense guides for anyone looking to start or change their career in tech. From choosing your first language to acing interviews.

Tech Salary Data

Transparent salary data for tech roles in Africa and worldwide, updated regularly with real market research.

AI Skills & Tools

Practical AI knowledge for developers. Build your first agent, get good at RAG, and pick the right AI coding tools for real work.

Bonaventure Ogeto

Bonaventure Ogeto

Founder and CEO, Mctaba Labs

Software engineer for 8+ years. He runs a Nairobi studio that ships products on M-Pesa, WhatsApp and AI, and teaches what the studio ships. He holds a BSc in Mathematics and Computer Science.

More about the author