reCAPTCHA v3 token solver and utility bill checker for TBCPay (Georgia)
Project description
TBCPay reCAPTCHA Solver
Get reCAPTCHA v3 tokens from TBCPay and check your utility bills in Tbilisi.
Now with pluggable solver backends -- use a real browser, a CAPTCHA solving service, or both.
What it does
- Grabs reCAPTCHA v3 tokens from TBCPay website
- Checks utility bills (water, electricity, telecom, etc.)
- Supports multiple CAPTCHA solving methods:
- zendriver (default) -- runs a real browser, gets high-score tokens for free
- 2captcha -- API service, human-powered, ~25-36s per token
- capsolver -- API service, AI-powered, ~3.4s per token
- Retries with exponential backoff, token caching, fallback chains
Setup
# Browser-based solver (default)
pip install tbcpay-recaptcha[zendriver]
# API-based solver
pip install tbcpay-recaptcha[capsolver]
# or
pip install tbcpay-recaptcha[twocaptcha]
# Everything
pip install tbcpay-recaptcha[all]
For API-based solvers, set your key:
export TBCPAY_CAPSOLVER_API_KEY="your-key-here"
# or
export TBCPAY_TWOCAPTCHA_API_KEY="your-key-here"
Basic usage
Checking water bill
import asyncio
from tbcpay_recaptcha import create_service
async def main():
async with create_service("water") as service:
result = await service.check_balance_async("YOUR_ACCOUNT_NUMBER")
print(result)
asyncio.run(main())
Checking electricity
import asyncio
from tbcpay_recaptcha import create_service
async def main():
async with create_service("electricity") as service:
result = await service.check_balance_async("YOUR_ACCOUNT_NUMBER")
print(result)
asyncio.run(main())
Using an API solver instead of a browser
import asyncio
from tbcpay_recaptcha import create_service
async def main():
async with create_service("water", backend="capsolver") as service:
result = await service.check_balance_async("YOUR_ACCOUNT_NUMBER")
print(result)
asyncio.run(main())
Hybrid: browser first, API fallback
If the browser fails, automatically fall back to an API solver:
import asyncio
from tbcpay_recaptcha import (
CachedSolver, FallbackSolver, RetrySolver,
SolverConfig, TBCPayService, get_service_config, get_solver,
)
async def main():
config = SolverConfig.from_env()
solver = CachedSolver(RetrySolver(FallbackSolver([
get_solver("zendriver", config),
get_solver("capsolver", config),
])))
svc = get_service_config("water")
service = TBCPayService(svc.service_id, svc.service_name, solver)
async with service:
result = await service.check_balance_async("YOUR_ACCOUNT_NUMBER")
print(result)
asyncio.run(main())
Running the examples
python examples/example_water.py YOUR_ACCOUNT_NUMBER
python examples/example_electricity.py YOUR_ACCOUNT_NUMBER
python examples/example_api_solver.py YOUR_ACCOUNT_NUMBER
python examples/example_hybrid.py YOUR_ACCOUNT_NUMBER
Adding other services
You need two things:
- The service ID from TBCPay
- Whether it uses step 1 or 2 (most use 2)
Finding service IDs
Open tbcpay.ge, go to your service, open browser devtools (F12), check the Network tab, and look for GetNextSteps requests. The service ID is right there in the payload.
Known services
These are built into the registry -- just use the name:
| Service | Name | ID | Step |
|---|---|---|---|
| Tbilisi Water | "water" |
2758 | 2 |
| Tbilisi Energy | "electricity" |
771 | 2 |
| TELMICO | "telmico" |
2817 | 2 |
| Tbilservice Group | "tbilservice" |
765 | 2 |
| CityCom | "citycom" |
915 | 1 |
Adding a custom service
from tbcpay_recaptcha import register_service, ServiceConfig, create_service
register_service("myservice", ServiceConfig(
service_id=1234,
service_name="My Service",
step_order=2,
))
async with create_service("myservice") as svc:
result = await svc.check_balance_async("YOUR_ACCOUNT")
Or just use the ID directly:
async with create_service(1234) as svc:
result = await svc.check_balance_async("YOUR_ACCOUNT")
How it works
The solver layer handles reCAPTCHA tokens:
ZendriverSolver-- starts a real Chromium browser via CDP, loads TBCPay, callsgrecaptcha.execute()to get tokens. High scores because it's a real browser.TwoCaptchaSolver/CapSolverSolver-- sends site key + URL to an API, gets a token back. Fast but lower scores.CachedSolver-- wraps any solver, caches tokens for 110 secondsRetrySolver-- wraps any solver, retries with exponential backoffFallbackSolver-- tries multiple solvers in order until one works
The service layer handles TBCPay:
- Makes async API requests to
api.tbcpay.ge - Parses the responses into something usable
- Returns standardized result dicts
Configuration
All settings can be set via environment variables:
| Variable | Default | Description |
|---|---|---|
TBCPAY_HEADLESS |
true |
Hide browser window |
TBCPAY_TWOCAPTCHA_API_KEY |
2captcha API key | |
TBCPAY_CAPSOLVER_API_KEY |
capsolver API key | |
TBCPAY_SITE_KEY |
(auto) | reCAPTCHA site key override |
TBCPAY_MAX_RETRIES |
3 |
Retry attempts |
TBCPAY_RETRY_DELAY |
1.0 |
Initial retry delay (seconds) |
TBCPAY_TOKEN_LIFETIME |
110 |
Token cache duration (seconds) |
TBCPAY_REQUEST_TIMEOUT |
15.0 |
HTTP request timeout (seconds) |
Or pass a SolverConfig directly:
from tbcpay_recaptcha import SolverConfig, create_service
config = SolverConfig(headless=False, max_retries=5)
service = create_service("water", config=config)
Response format
When everything works:
{
'account_id': '123456',
'service': 'Tbilisi Water',
'status': 'success',
'customer_name': 'John Doe',
'balance': 0.0,
'amount_to_pay': 0.0,
'currency': 'GEL',
'can_pay': True,
'raw_data': {...}
}
When something breaks:
{
'account_id': '123456',
'service': 'Tbilisi Water',
'status': 'error',
'error': 'Request timeout'
}
Which solver should I use?
| Solver | Cost | Speed | Score | Best for |
|---|---|---|---|---|
| zendriver | Free | ~5s | High (0.7-0.9) | Default, personal use |
| capsolver | $1/1000 | ~3.4s | Low (~0.1) | Fast fallback, high volume |
| 2captcha | $1.45-2.99/1000 | ~25-36s | Low (~0.1) | Most reliable API |
Browser-based (zendriver) gets much higher scores because it runs real Chromium. API services generate tokens remotely, so Google gives them low scores. For TBCPay this doesn't seem to matter -- they accept low-score tokens. But if they tighten the threshold, zendriver is the way to go.
Requirements
- Python 3.10+
- One of: zendriver, 2captcha-python, capsolver
License
MIT. Do whatever you want with it.
Notes
This is for personal use. Don't abuse TBCPay's API or you might get rate limited. Account numbers and tokens are sensitive -- don't commit them to git or share them publicly.
Check out SERVICES.md if you want more details on adding new services.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tbcpay_recaptcha-2.0.0.tar.gz.
File metadata
- Download URL: tbcpay_recaptcha-2.0.0.tar.gz
- Upload date:
- Size: 18.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e031300ec60849648b4108bec0a3d51c193d2b9a7a001c8882f72a791b4799be
|
|
| MD5 |
1965c4203fa01af6abe726268cf7dabd
|
|
| BLAKE2b-256 |
d5215dbacd4f020c08aace5fa820cf3fbbffc0ac7a7c696b108c0ca69c8c7fcc
|
File details
Details for the file tbcpay_recaptcha-2.0.0-py3-none-any.whl.
File metadata
- Download URL: tbcpay_recaptcha-2.0.0-py3-none-any.whl
- Upload date:
- Size: 18.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1b4ec2bee86339a17068d71456648d517e3e85c76fefc42615057043ce4d45fa
|
|
| MD5 |
b8140352f3e4b4e78880548ddc5d5356
|
|
| BLAKE2b-256 |
b918264ef05b0ce32af07cf4765c0baa1b3f465d0618230c150e81645e7315d6
|