---
name: ravn-check-mobile-before-sms
description: Use before sending SMS when someone needs to confirm each phone number is valid and a real mobile line, using number-plan checks then a live carrier lookup.
title: Check Numbers Are Mobile Before Texting — Ravn
---
# Check numbers are real mobiles before texting

Before a text campaign, confirm each number is valid, put it in E.164 format, and check it is a real mobile line rather than a landline or VoIP number. It runs in two passes: a cheap number-plan check for everyone, then a live carrier check only where it matters.

## When to use

- The user is about to send SMS and wants to avoid texting landlines, toll-free or VoIP numbers.
- Phone numbers came in mixed formats from forms or imports.
- "Which of these numbers can actually receive a text?"

## Before you start

1. Check the connection: `npx ravn whoami` (free).
2. `phone_to_carrier` needs your own provider key connected — run `ravn keys add twilio` first; this tool runs on your own provider account. If it returns 403 `provider_key_required`, stop and tell the human to add their key. `validate_phone` is ours and needs no key; it uses the number plan only (`carrier_checked: false`). Every call is one lookup; misses are free.
3. Ask which country most numbers are from. National numbers without a `+` need a `country` (ISO 2-letter code); the default is US.
4. Confirm the user has consent to text these people. This skill checks numbers, not permission.

## Steps

1. Pass 1, format and line type from the number plan, for everyone:

```bash
npx ravn enrich contacts.csv --tool validate_phone --map phone=Phone,country=Country --dry-run
npx ravn enrich contacts.csv --tool validate_phone --map phone=Phone,country=Country --limit 10 --out sample.csv
npx ravn enrich contacts.csv --tool validate_phone --map phone=Phone,country=Country --out pass1.csv
```

If there is no country column, use `--column Phone` and numbers default to US. Fill empty country cells (for example with `US`) first, or those rows come back as `error` with `invalid_input`. Single number over MCP:

```json
{ "phone": "(415) 555-0134", "country": "US" }
```

2. Sort pass 1 results:
   - `rw_valid` false or `rw_status` `not_found`: remove.
   - `rw_line_type` `landline` or `toll_free`: remove from the SMS list.
   - `mobile`, `voip` or unclear: keep for pass 2.

   Write the kept rows to `keep.csv`, renaming `rw_phone` to `phone_e164` and `rw_line_type` to `plan_line_type`, and dropping the other pass 1 `rw_*` columns, so pass 2 does not produce clashing column names.
3. Pass 2, live carrier check, only on the kept rows. Number-plan line type can be wrong when numbers have been ported, so this is the real answer.

```bash
npx ravn enrich keep.csv --tool phone_to_carrier --column phone_e164 --dry-run
npx ravn enrich keep.csv --tool phone_to_carrier --column phone_e164 --out pass2.csv
```

The input is the E.164 number from pass 1. The dry run shows how many lookups the pass will use.
4. If `phone_to_carrier` returns 403 `provider_key_required`, the account has no carrier provider key connected. Tell the human to add one with `ravn keys add twilio`, and in the meantime send them the pass 1 result with a clear note that line types are from the number plan only.
5. Keep only rows where the live `line_type` is `mobile`. Flag non-fixed VoIP separately; whether to text those is the user's call.

## Output

`sms-ready.csv` with original columns plus:

- From pass 1: `phone_e164` and `plan_line_type` (the number-plan guess).
- From pass 2: `rw_status` (`ok`, `not_found`, `error`, `dropped`), `rw_phone`, `rw_line_type` (live), the carrier name, and `rw_carrier_checked` true.
- `sms_ok`: yes or no, with `sms_reason` (invalid, landline, toll_free, voip, mobile).

Also `removed.csv` and a count per reason.

## Rules

- Never text anyone who opted out or replied STOP. Remove them before you start. See [/privacy#optout](https://askravn.com/privacy#optout).
- A valid mobile is not consent. Remind the user that texting rules in their country still apply.
- No FCRA uses: do not check numbers to screen people for credit, employment, insurance or housing.
- On a 429 `fair_use_exhausted` or a 403 `provider_key_required`, stop and tell the human.

## Example prompt

> We're texting 2,000 customers a delivery update next week. Phone numbers are all over the place. Make sure we only text real mobiles and fix the formatting.
