Bulk Credit Lookups: Screening a List of Phone Numbers

Running 300 credit lookups is a different job than running one. The list has to qualify, the file needs cleaning, the script has to retry safely, and the results need a plan. This is the workflow we'd hand a new ops hire.

Hands typing on a laptop showing a spreadsheet of rows, the starting point for a bulk credit check
Photo by Bluestonex on Unsplash
On this page
  1. Lists that qualify, and lists that don’t
  2. Prepare the file before you write any code
  3. A script you can adapt
  4. What a bulk credit check costs
  5. Reading 300 results at once
  6. Keep the data like you mean it
  7. Frequently asked questions

A bulk credit check means running credit lookups on a whole list of people at once instead of one at a time, usually through an API. With phone numbers, that’s a CSV of numbers in and a file of names, addresses, scores and credit profiles out. The tech is the easy part. What makes a bulk run safe is the list itself: every single person on it needs their own permissible purpose, exactly as if you’d checked them one by one.

Lists that qualify, and lists that don’t

The Fair Credit Reporting Act doesn’t have a bulk exception. Section 604 lists the reasons someone can get a consumer report, and they apply per person. So the question is never “can I screen this list?” It’s “does each person on this list have a reason to be on it?”

Lists that usually qualify:

  • A backlog of applications. A property manager’s 300 rental applications from a spring leasing push, each with a signed consent checkbox (the tenant screening guide covers what that screening should look at). A dealer’s financing applications from a weekend event.
  • Consented leads. Inbound leads who ticked a box authorizing your business, by name, to check their credit.

Lists that don’t:

  • Purchased or scraped lists where nobody agreed to anything with you.
  • A CRM full of old contacts you’d like to “score” to decide who to market to.
  • Cold lists for firm offers of credit. That’s prescreening, a separate process under section 604(c) that runs through the bureaus, requires a firm offer, and comes with a consumer opt-out (the CFPB explains how those lists work). Our post on prescreened offers explains it from the consumer’s side.

The stakes scale with the list, which is the part people miss. Under section 616, willful violations can cost actual damages or statutory damages of $100 to $1,000 per consumer, plus punitive damages and attorney’s fees. One bad lookup is a problem. A bad list of 800 is a much bigger one. This isn’t legal advice, and if a list feels borderline, ask your lawyer before you run it. Our permissible purpose guide covers the gray areas.

Prepare the file before you write any code

Half of a clean bulk run happens in the spreadsheet. For each row, you want:

Column Why it matters
phone The only required lookup field. Any U.S. format works, but normalize anyway so you can dedupe.
purpose Your reason for this specific person, like consent or rental_application.
reference Your own ID for the person (application ID, account number). It comes back in the response.
consent_at When and how they agreed. Not sent to us, but you’ll want it if anyone ever asks.

Then clean it:

  1. Normalize numbers to 10 digits. “(555) 555-0142”, “555.555.0142” and “+1 555 555 0142” are one person.
  2. Dedupe. Duplicate rows are the most common reason bulk runs cost more than expected.
  3. Drop rows without a purpose. If you can’t fill that column honestly, the row doesn’t belong in the file.
  4. Add identity fields where you have them. If an application already collected first name, last name or address, include them. They help confirm the match when a number is new, shared on a family plan or recently ported.
Close-up of a dark code editor with colorful JavaScript on the screen
Photo by Glen Carrie on Unsplash

A script you can adapt

A small Python version below reads the CSV, sends one lookup per row, retries politely when rate limited, and writes a results file. Run it first with a test key (keys starting pncs_test_ return example people and are never charged), then switch to your live key.

import csv, os, time, requests

API = "https://api.phonenumbercreditscore.com/v1/lookups"
HEADERS = {"Authorization": f"Bearer {os.environ['PNCS_KEY']}"}

def lookup(row):
    body = {"phone": row["phone"], "purpose": row["purpose"], "reference": row["reference"]}
    for attempt in range(5):
        r = requests.post(API, json=body, timeout=30,
                          headers={**HEADERS, "Idempotency-Key": row["reference"]})
        if r.status_code == 429 or r.status_code >= 500:
            time.sleep(2 ** attempt)
            continue
        return r
    return r

with open("applicants.csv") as f_in, open("results.csv", "w", newline="") as f_out:
    out = csv.writer(f_out)
    out.writerow(["reference", "status", "name", "score", "line_type", "fraud_score"])
    for row in csv.DictReader(f_in):
        r = lookup(row)
        if r.status_code == 200:
            d = r.json()
            out.writerow([row["reference"], "ok", d["name"], d["score"]["value"],
                          d["phone_details"]["line_type"], d["phone_details"]["fraud_score"]])
        else:
            err = r.json().get("error", {}).get("code", r.status_code)
            out.writerow([row["reference"], err, "", "", "", ""])

A few details that matter at volume:

  • The Idempotency-Key header makes retries safe. If a request times out and you send it again with the same key, you won’t be charged twice. Using your own reference as the key is the simplest way to guarantee it.
  • Back off on 429s and 5xx errors. A rate_limited response means slow down, not fail. The exponential sleep above handles both. Don’t retry other 4xx errors; those need a fix in the row, not another attempt.
  • Sequential is fine. A few hundred lookups at a few seconds each finishes over a coffee break. If you add concurrency, keep it modest.
  • Webhooks can tell your system when a lookup completes, which helps if results feed a CRM or a review queue rather than a CSV. Our post on credit webhooks for lead routing shows the pattern, and the credit score API guide covers the request and response in full.

What a bulk credit check costs

API pricing is flat: $49 a month or $149 a year, plus $7.50 per report, with no cap on how many you run in a month. Lookups that don’t match anyone aren’t charged.

Say the property manager above runs 340 applications on the monthly plan, and 322 of them match. That’s $49 plus 322 × $7.50, or $2,464 for the month. If they want account-by-account history on the 40 applicants who are borderline, the enhanced report adds $2 each, another $80. Once your lists add up to 1,000 or more lookups a month, you qualify for volume rates; email [email protected]. The full breakdown is in credit API pricing per report, and the API page has the current plans.

Two cost controls worth turning on before a big run: a spending limit on the account, and IP allow lists so only your server can use the key.

Reading 300 results at once

The output of a bulk run sorts itself into a few piles:

  • Matched and scored. The bulk of the list. Apply your written criteria the same way to every row, ideally in code, so nobody gets judged differently because a reviewer was tired at row 280.
  • No match. The number didn’t tie to a credit file. Free, and usually a reason to ask the person for another number or to send name and address with the request.
  • Frozen file. The person has frozen their TransUnion file. Ask them to lift it temporarily and run them again.
  • Too new to score. A real person with too little history. Decide in advance how your policy treats thin credit files instead of improvising.

Before anyone acts on the file, spot-check it. Pull ten matched rows at random and compare the returned name and address against the original applications. If they line up, good. If two of the ten come back under a different name, you’ve probably got family-plan or work numbers in the list, and it’s worth re-running those rows with the applicant’s name and address included. Ten minutes of checking beats explaining to an applicant why you judged them on their brother’s credit.

Also watch the phone details column. A list of rental applicants with a cluster of brand-new VoIP numbers and high fraud scores is telling you something about where those applications came from, and it’s a lot easier to see in a sorted spreadsheet than one lookup at a time.

And if any of those results lead you to deny an application or offer worse terms, the FCRA requires an adverse action notice to that person, naming TransUnion as the source. With a batch, that can mean dozens of notices in one afternoon. Build the template before the run, not after. Our guide to the landlord adverse action notice has the required pieces.

Keep the data like you mean it

A results file with names, addresses and credit scores for hundreds of people is exactly the kind of thing that shouldn’t live in a shared drive called “screening_FINAL_v3.csv.” Businesses covered by the FTC’s Safeguards Rule (16 CFR Part 314) have specific obligations, and everyone else should behave as if they do: encrypt it, limit who can open it, delete it when the decision is made, and never share or resell it. Our compliance page sums up what we expect of every account.

Then run a test file of ten rows first. Every bulk job that goes sideways does it in the first ten.

Frequently asked questions

Can I run a bulk credit check on a purchased lead list?

Not unless every person on it gave you, by name, permission to check their credit, or has another permissible purpose with your business. Screening a bought or cold list to decide who to market to isn't allowed. Sending firm offers of credit to a list is a separate, regulated process called prescreening.

Will the people on the list be notified?

No. Every lookup is a soft pull, so they aren't notified and their scores aren't affected. You still need a permissible purpose for each one.

What happens when a number doesn't match anyone?

You get a no_match response and you aren't charged. If we find the person but their file is frozen or too new to score, the response says which, and that counts as a lookup because the person was found.

Is there a monthly limit?

No. The API plans have no monthly cap on lookups, at $7.50 for each one that matches. Once you reach 1,000 lookups a month, you qualify for volume rates: email [email protected].

Share this article LinkedIn X Facebook Email

Written by

Jordan AveryHead of Content

Jordan Avery runs the blog at Phone Number Credit Score and writes about phone data, credit scores, tenant and lead screening, and the rules that come with all of it. Most posts start as a question a customer asked us.

Try it now

Have a phone number? Find their credit score.

Name, current address and real FICO® Score 4 from TransUnion data. Results in seconds. As low as $9.99.

Have a phone number? Find their score.

Type in any U.S. phone number. We’ll tell you who it belongs to, where they live and their real credit score.

  • Soft pull, they’re never notified
  • Results in seconds
  • As low as $9.99

Use it for a permissible purpose, like the person’s OK. The rules