Independent engineer · Python & Go

For data that is hard to get, and work that has to keep running.

I'm Tohfa Akib, an independent engineer. I collect data from protected, JavaScript-heavy and stateful websites, automate browser workflows, and build the Python and Go backends behind them. Often the work starts where a quick script stopped working. You work with me directly.

7+years of hands-on work 88completed Upwork jobs Hundredsof projects overall
extract · product listing → rowsSample data
Raw inputshop.example / page 1 of 3
<div class="card"><h2>Desk Lamp Pro</h2><span class="price">$1,299.00</span> ...
Structured output0 rows
namepricestock
Desk Lamp Pro1299.00in_stock
Prices normalised · duplicates removed
Illustration with made-up data. The Lab has versions you can drive yourself.
7+years building scrapers, automation and backends
Hundredsof projects delivered, on and off Upwork
88completed jobs on Upwork
Python · Goplus JavaScript, SQL, Linux and cloud
PythonGoScrapyPlaywrightSeleniumrequestsFastAPIDjango RESTPostgreSQLMongoDBRedisCelery / arqDockerAWS LambdaLinuxRaspberry PiHAProxyTelegram & Slack bots
Problems I'm brought in for

The script runs. The data is wrong.

Getting a first version working is rarely the hard part. These are the problems that decide whether a project actually delivers, with real work behind each one.

"The site blocks us, or serves a page that only looks right."

Bot detection such as Akamai or DataDome judges the whole session: browser behaviour, cookies, request order and timing. A failed check can still return 200. The work starts with diagnosing what the site actually sees, then choosing an approach that is reliable and appropriate for your use.

"It worked on the first pages, then returned nothing."

The page is assembled by JavaScript from undocumented requests, or the session quietly expired. Both can return status 200 with no data; the fix is understanding the application's real request flow.

"We have 3,000 rows but half are the same."

Paging is stateful: asking for page 2 quietly returns page 1. The collector has to carry state forward and prove each page is new.

"It crashes overnight and starts again from zero."

No checkpoints and no idempotent writes. Long jobs need to resume where they stopped without duplicating anything.

"The site limits us, so we need more IP addresses."

Sometimes that is true, and then the infrastructure must rotate without taking itself offline. Often the fix is pacing and a smarter crawl.

"The API timed out. Did the order go through?"

A lost response is not a failure. Blind retries double-book; the integration needs an explicit unknown state and reconciliation.

"There is a login with a one-time code."

Design the human step in: a person enters the code once, the session is reused, and the rest runs unattended.

See why quick collectors fail →An interactive comparison, about two minutes.
Start here

What are you trying to get done?

Pick the closest one. No technical words needed. You'll see how I'd approach it, work I've done that's close, and a sensible next step.

Your goal: Collect data from websites

You need data that lives on someone else's website.

I build extractors that handle pagination, logins you own, changing layouts and sites that block simple scripts. You get a clean file or feed, and the code that produced it.

Next step

Send me the site, the fields you need and roughly how many records.

Start with this →
Selected work

Problems I've solved, and how

Each case explains the problem, what made it hard, the approach and what was delivered. Client names and data stay private.

access ladder · cheapest working rung first1 · plain HTTP clientfast, cheap2 · browser-like TLS clientmatched fingerprint3 · real browserPlaywright, fallback onlyWebForms gridstateful pagingrecords~3,300members +sub-accountsgap check vslistingresumable crawl · output verified against the public listing
Protected sources

Protected Directory Collector

About 3,300 member and sub-account records from a Cloudflare-protected directory, with a three-step access ladder and a resumable crawl.

~3,300member and sub-account records
3-stepaccess ladder, cheapest first
Gap checkoutput compared to the listing
TLS fingerprintingCloudflareresumable
Read the case study
clientsHTTP / SOCKSHAProxyadmin socket · livedrain → rotate → addLTE modem 1serving · new carrier IPLTE modem 2serving · new carrier IPLTE modem 3rebooting · route restoreLTE modem 4serving · new carrier IPRaspberry Pi · Go scheduler rotates one modem at a time
Infrastructure

Mobile Proxy Farm

LTE dongles on a Raspberry Pi behind HAProxy, with ordered recovery after each reboot and a scheduler that rotates one modem at a time.

GoHAProxypolicy routing
Read the case study
p1p2p3p4p5p6county portal · one postback per page__VIEWSTATE carried page to pagecheckpoint.jsonresume here · finished records skippedpermits.xlsx2,478 rows · contractor details
Data extraction

Permit Exporter: 2,478 Records

Every 2026 roofing, siding, and window permit from a county portal, with contractor details, delivered as a workbook plus a resumable script.

ASP.NET postbackscheckpointsrequests-only
Read the case study
orderseller dashboardbooking workerarq · idempotency keycourier APIcreate shipmenttimeout: booked?uncertain statelook up, never blind-retryreconcilerconfirm or retry oncewebhooks → dedupe → statusrepeated deliveries collapse to one updateFastAPI · PostgreSQL · 3 couriers
Backend design

Failure-Aware Courier Booking

Courier integration architecture for online sellers: controlled retries, explicit handling of uncertain bookings, and deduplicated delivery updates.

idempotencywebhookssystem design
Read the case study
ProthomaloKalerkanthoBd PratidinIttefaqDhaka TribuneSamakalJagoNews24JugantorNTV BDScrapy spidersscheduled crawlsDjango + DRFauth REST APIAndroid app
Personal product · mobile + backend

BDNewsToday: All Bangla Newspapers

A news aggregator app for the most popular Bangla newspapers, backed by Scrapy spiders and an authenticated Django REST API.

ScrapyDjango RESTAndroid
Read the case study

See all work, including smaller projects

Before and after

What changes when the work is automated

Drag the handle. A typical weekly data task, done by hand on the left and by a scheduled job on the right. Hours are illustrative.

How we work

A clear path from first message to handover

You never pay to find out whether something is possible. A paid proof of concept is only suggested when a source or system is genuinely uncertain.

  1. Free

    You describe it

    In plain words. A few sentences is enough to start.

  2. Free

    I assess it

    Within two working days: is it doable, what are the risks, what would it take.

  3. If useful

    Proof of concept

    A small paid sample on the real source when there's real uncertainty. Otherwise, straight to a quote.

  4. Build

    Fixed scope with written acceptance checks, or hourly for open-ended work. Regular progress you can see.

  5. Handover

    You own the code, the data and a short runbook. Maintenance is available, never required.

What clients say

Selected feedback

Exact words from reviews of completed contracts.

Amazing job, amazing freelancer. Efficient and quick. Would highly recommend.
List scraper for a sales company · Feb 2020
helpful, responsive, and overall great work
PDF to CSV data extraction · Aug 2021
Fast and Quality work result
Website data collection · Dec 2021
Next step

Tell me what's slowing you down.

Describe the problem in your own words, even if you are not sure what kind of solution you need. I reply within two working days with an honest assessment.