---
title: "Guard text sending against SMS pumping · Agent Wranglers"
url: https://agentwranglers.se/playbook/notifications/text-messages/sms-pumping
updated: 2026-10-20
licence: "All rights reserved"
---

# Guard text sending against SMS pumping

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Required
- Chapter: [Text messages](https://agentwranglers.se/playbook/notifications/text-messages)
- Rule: Limit who can make you send a text, to which countries, and how often. SMS pumping fraud sends your codes to premium numbers and bills you.
- How: Allow only the countries where you have customers in the provider's geo settings. Rate-limit code requests per phone number, per number prefix, per IP address and per account, such as 3 per number per hour. Require a form check, such as a challenge, before the first text. Alert when sends to one country or prefix jump, or when the share of codes entered falls below a set line, such as 50 percent. Alert too when the daily text cost passes its budget. Many providers offer pumping protection, such as Twilio Verify Fraud Guard. General limits live in [limit requests per client](https://agentwranglers.se/playbook/adversarial-testing/abuse-and-limits/limit-requests).
- Check: A test asks for a code to a number in a blocked country and expects a refusal. A script asks for 10 codes to one number in a minute and gets at most 3. An alert fires on a daily cost above budget.

Example:

```js
const MAX_CODES_PER_NUMBER_PER_HOUR = 3;
const ALLOWED_COUNTRIES = new Set(['SE', 'NO', 'DK', 'FI']);

export async function mayTextCode(phone, ip) {
  if (!ALLOWED_COUNTRIES.has(phone.country)) return false;
  const recent = await limiter.hits(`sms:${phone.e164}`, 3600);
  return recent < MAX_CODES_PER_NUMBER_PER_HOUR && (await limiter.hits(`sms-ip:${ip}`, 3600)) < 10;
}
```

```python
MAX_CODES_PER_NUMBER_PER_HOUR = 3
ALLOWED_COUNTRIES = {"SE", "NO", "DK", "FI"}

def may_text_code(phone, ip: str) -> bool:
    if phone.country not in ALLOWED_COUNTRIES:
        return False
    return (limiter.hits(f"sms:{phone.e164}", 3600) < MAX_CODES_PER_NUMBER_PER_HOUR
            and limiter.hits(f"sms-ip:{ip}", 3600) < 10)
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers notifications playbook: https://agentwranglers.se/playbook/notifications/text-messages/sms-pumping`.

- Previous: [Stop at the first STOP](https://agentwranglers.se/playbook/notifications/text-messages/sms-stop-keywords)
- Next: [Store phone numbers in E.164](https://agentwranglers.se/playbook/notifications/text-messages/e164-phone-numbers)
- [Text messages](https://agentwranglers.se/playbook/notifications/text-messages)
