AI Analytics

Technical writing

The $800 billion bailout: using SBA PPP data to trace who got pandemic relief

· AI Analytics
Regulatory dataSBAPPPPandemic reliefFraudOpen data

In March 2020, Congress authorized the Paycheck Protection Program to provide forgivable loans during the pandemic. By the time the program closed in May 2021, the SBA had approved 11.8 million loans totaling approximately $793 billion in principal. The public disclosure expanded in stages, and the current SBA files are materially different from the first release.

The FOIA fight

The SBA's initial position was that borrower names and loan amounts were proprietary business information, exempt from disclosure under FOIA Exemption 4. In June 2020, a coalition of news organizations—ProPublica, the New York Times, the Washington Post, and others—filed suit in the U.S. District Court for the District of Columbia. The organizations argued that businesses receiving public funds had no legitimate privacy interest in that fact.

On July 6, 2020, SBA released borrower names and loan ranges for loans of $150,000 or more. For smaller loans, it released loan-level rows with fields such as exact amount, ZIP, industry, business type, demographics, and jobs reported, but omitted borrower names and street addresses. That smaller-loan release was not aggregate-only.

In WP Company LLC v. SBA (D.D.C. Nos. 20-1240 and 20-1614), the district court ordered additional borrower information released on November 5, 2020; it denied SBA's requested stay on November 24, and the agency made the ordered data available on December 1. Later releases added program-status and forgiveness fields. The current official catalog must be treated as its own dated snapshot rather than inferred from the July schema.

Where the data lives

The canonical source is https://data.sba.gov/dataset/ppp-foia. The current catalog labels the release with snapshot suffix 240930 and publishes 13 loan-level CSV resources:

Both tiers use loan-level rows and include the loan number, exact amount, industry, location fields, and borrower-identity fields. Some individual identity cells are blank or carry an SBA redaction label. The public files do not expose borrower EINs. A complete cohort must acquire all 13 resources, preserve their hashes, and verify thatLoanNumber is unique before aggregation.

The catalog says the dataset covers all disbursed PPP loans. The release is large enough that a bounded workflow should stream selected columns or convert one shard at a time, instead of loading the national file set into memory at once.

Key fields

The current loan-level resource files contain the following columns relevant to investigation work:

FieldNotes
LoanNumberPrimary key. Use for deduplication across batch files.
BorrowerNameLegal name as submitted. Inconsistently normalized; “LLC” vs. “L.L.C.” are separate strings.
BorrowerAddress, BorrowerCity, BorrowerState, BorrowerZipStreet address as submitted. Useful for clustering multiple loans at the same physical location.
CurrentApprovalAmountExact loan amount in dollars. This replaced the original range buckets after court disclosure orders.
DateApprovedSBA approval date. First-draw loans clustered heavily in April–May 2020; second-draw in January–March 2021.
OriginatingLender, ServicingLenderNameNames carried in the source for origination and servicing. Case counts are selected outcomes, not lender-level misconduct rates without a complete denominator.
CDCongressional district in STATE-NN format. Enables political geography analysis.
NAICSCodeSix-digit NAICS industry code. Essential for jobs plausibility checks.
BusinessTypeLegal entity type: Corporation, LLC, Sole Proprietorship, Non-Profit Organization, etc.
NonProfitBorrower-reported flag. It cannot establish or disprove tax-exempt status, and a BMF non-match is inconclusive—especially for churches not required to apply.
JobsReportedEmployee count as reported by the borrower. A discrepancy can support follow-up, but is not proof of a false statement.
ForgivenessAmountReported amount forgiven. A null value can reflect status, timing, or source completeness and is not a fraud finding.
ForgivenessDateDate of forgiveness decision.
LoanStatusPaid in Full, Charged Off, Exemption 4 (SBA declined to disclose), Active Un-Disbursed.

The scale

The program operated in two rounds. The first draw (April–August 2020) approved 5.2 million loans averaging $101,000 each. Congress then reauthorized the program for a second draw (January–May 2021), adding 6.6 million more loans skewing smaller—average $47,000—as solo proprietors and gig workers became eligible.

The first 2020 disclosure used a $150,000 threshold and withheld borrower identities in the smaller-loan tier. The current SBA FOIA release is different: it publishes loan-level resources for both tiers, although some identity fields remain individually redacted. Historical reporting about the initial disclosure must not be used to describe the present download schema.

SBA OIG Report 25-12 says that, as of May 24, 2024, SBA had forgiven more than 10.5 million PPP loans totaling more than $750 billion. Separately, OIG Report 23-09 estimated more than $200 billion in potentially fraudulent disbursements across the combined approximately $1.2 trillion COVID EIDL and PPP programs—at least 17 percent. That is an OIG estimate across two programs, not a PPP-only adjudicated loss.

Questions that require official corroboration

Entity-existence allegations

An allegation that a borrower did not exist requires a source that can actually establish the borrower's legal identity and status at the relevant date. The public PPP files do not expose a borrower EIN, and federal tax-return history is not a public comparison field. State-registry non-matches can be useful leads, but sole proprietors and other lawful entity types may not appear in a corporation registry.

The public IRS EO BMF is not a business-incorporation registry. Entity existence has to be tested against the relevant official registration and case records. Name and location can nominate a candidate for review, but a non-match does not establish that a borrower was fictitious.

Loans to debarred federal contractors

The CARES Act's statutory text was not the whole eligibility rule. SBA's operative PPP rules made an applicant that was presently suspended, debarred, or proposed for debarment ineligible at the time of application. A past or expired exclusion is not the same fact. The SAM.gov exclusions database publishes exclusion records, but only an exact official identifier and source dates can confirm the borrower's identity and whether an exclusion was current when the application was made.

SAM.gov entity names and PPP borrower names can be inconsistently formatted. A fuzzy name-and-ZIP match is candidate discovery only; it must never be published as a confirmed exclusion join.

Multiple loans associated with one submitted address

Grouping public_150k_plus_240930.csv by submittedBorrowerAddress and BorrowerZip can nominate a private review candidate. A shared office, campus, registered agent, mail center, related entity, or administrative address can be lawful, so an address cluster neither confirms common control nor establishes duplicate or ineligible borrowing.

Publication requires the relevant SBA loan numbers and a separate official record that establishes the relationship or action. The public output in this project therefore does not expose address-cluster accusation lists.

Jobs reported versus industry benchmarks

PPP loan calculations generally used a multiple of eligible average monthly payroll, subject to program-period rules. The Bureau of Labor Statistics Quarterly Census of Employment and Wages publishes establishment counts, employment, total wages, and average annual or weekly wages by industry and geography; it does not publish a median establishment payroll. Comparing JobsReported with those aggregates can generate a review candidate, but coverage exclusions and suppressed cells must be retained.

CurrentApprovalAmount / JobsReported / 2.5 is only an implied-payroll diagnostic. It must be recomputed from the exact source values and checked against the applicable program rules. JobsReported may not equal the payroll headcount used in the loan calculation, so the ratio is neither an eligibility test nor proof of a false statement.

Why an IRS non-match is inconclusive

The PPP NonProfit flag was borrower-reported. The IRS EO BMF is published monthly, but it is an account/status extract rather than a census or a uniform recognition list: its STATUS field must be retained, and it excludes self-declared organizations and churches or other organizations that were not required to apply and did not apply. The public PPP files do not expose EINs, so a name-and-location comparison cannot establish a false tax-exempt claim. Confirmation requires an exact official identifier or an official agency or court record.

Cross-reference opportunities

SAM.gov debarments

The System for Award Management exclusions file is available from sam.gov/data-services. The source includes exclusion records and their effective dates. Because the public PPP files omit EIN and UEI, normalized name and ZIP can only nominate a private review candidate; they cannot establish that a borrower is the excluded entity or when an exclusion applied to that borrower.

A public claim requires an exact official identifier or a separate agency or court record that identifies both the borrower and the exclusion. Candidate rows must remain unpublished until that evidence exists.

IRS Business Master File

The IRS publishes the EO BMF account/status extract at irs.gov/charities-non-profits/exempt-organizations-business-master-file-extract-eo-bmf. Relevant fields include EIN, STATUS, organization name, IRS ruling month, NTEE code, filing-requirement code, and financial fields from the latest reflected return. A recognition cohort requires an explicit STATUS filter. The extract does not cover every tax-exempt organization and NTEE X is religion-related, not a definitive church flag.

An exact EIN would be the strongest join key, but it is not present in the public PPP files. A name-and-location match can support private candidate discovery; a fuzzy match or non-match must not be published as identity, status, fraud, or evasion evidence. This constraint is especially important for churches that lawfully may have neither a BMF row nor a Form 990.

DOJ PPP fraud prosecutions

The Department of Justice maintains public case releases. Its April 9, 2024 COVID-19 Fraud Enforcement Task Force report said member agencies had charged more than 3,500 defendants across pandemic-fraud programs. That is a dated, cross-program aggregate; it is not a PPP-only defendant count and does not establish that PPP cases were a majority.

Each release can be structured with its case number, court, allegation or adjudicated outcome, and source URL. A name, lender, and amount comparison to PPP data is candidate discovery only unless the official case record supplies the SBA loan number or another exact identifier. Allegations, guilty pleas, convictions, dismissals, and sentences must remain separate outcome fields. The Corporate Prosecution Registry at Duke and UVA is a useful companion for corporate-entity resolutions.

SEC enforcement actions

SEC litigation releases and administrative orders can identify PPP-related allegations involving securities-market participants. Those records should be published with the SEC action number, filing date, procedural posture, and source URL. A borrower-name comparison to PPP data remains unconfirmed unless the official action identifies the loan or another exact record key.

Congressional district analysis

The CD field allows aggregation by congressional district. Joining district-level PPP totals to House and Senate vote records on the CARES Act, to FEC campaign finance data, and to American Community Survey income data produces a political economy picture of which districts received disproportionate relief relative to economic need. Several analyses found that districts represented by legislators who voted against the CARES Act nonetheless received program funds at the same per-capita rate as districts whose representatives voted for it—a fact that generated friction during the program's political aftermath.

Lobbying-adjacent businesses are identifiable by cross-referencing the PPP borrower list with the Lobbying Disclosure Act database (lobbyingdisclosure.house.gov). Trade associations, law firms with federal practice groups, and K Street consulting firms that received PPP loans while simultaneously lobbying on pandemic-related legislation created conflicts that drew oversight attention.

The EIDL companion dataset

The PPP ran alongside the Economic Injury Disaster Loan program, which provided low-interest loans plus emergency advance grants. EIDL data is separately available from data.sba.gov under FOIA releases, and its disclosure fields differ. A name-and-ZIP comparison can nominate possible dual-program recipients for private review, but it does not confirm identity or establish that expenses were counted twice.

Python analysis: a source-native religious-organization cohort

The following code verifies and streams all 13 files in the pinned 240930release, then filters the SBA's own NAICSCode field to 813110, Religious Organizations. That source-native category supports aggregate analysis without a fuzzy identity join. It is broader than an IRS determination that an entity is a church, and it does not establish tax status or misconduct.

import pandas as pd
from pathlib import Path

# Pin the complete current SBA release listed on the PPP FOIA catalog. The
# 240930 snapshot has one 150k-plus file and 12 up-to-150k files. All 13 are
# loan-level resources. Refresh the manifest when SBA posts a newer release.
SNAPSHOT = "240930"
files = [Path("public_150k_plus_" + SNAPSHOT + ".csv")]
files += [
    Path("public_up_to_150k_" + str(part) + "_" + SNAPSHOT + ".csv")
    for part in range(1, 13)
]
missing = [str(path) for path in files if not path.is_file()]
if missing:
    raise FileNotFoundError("Missing SBA PPP snapshot files: " + ", ".join(missing))

# Stream only fields needed for this aggregate. Do not ingest borrower names or
# street addresses into the output workflow.
religious_parts = []
usecols = [
    "LoanNumber",
    "BorrowerState",
    "NAICSCode",
    "CurrentApprovalAmount",
    "ForgivenessAmount",
]
for path in files:
    for chunk in pd.read_csv(
        path,
        usecols=usecols,
        dtype={"LoanNumber": str, "BorrowerState": str, "NAICSCode": str},
        chunksize=250_000,
        low_memory=False,
    ):
        religious_parts.append(chunk.loc[chunk["NAICSCode"] == "813110"].copy())

if not religious_parts:
    raise RuntimeError("No rows were read from the pinned SBA resources")
religious = pd.concat(religious_parts, ignore_index=True)
if religious.empty:
    raise RuntimeError("No NAICS 813110 rows were found in the pinned SBA resources")
if religious["LoanNumber"].isna().any() or religious["LoanNumber"].duplicated().any():
    raise RuntimeError("LoanNumber integrity check failed; review the source snapshot")

# Build a source-native cohort using the NAICS value in the SBA file.
# 813110 means Religious Organizations; it is not an IRS church determination.
# Publish aggregate statistics, not an accusation list or street-address file.
religious["forgiveness_recorded"] = religious["ForgivenessAmount"].notna()
state_summary = (
    religious.groupby("BorrowerState", dropna=False)
    .agg(
        loans=("LoanNumber", "count"),
        approved_amount=("CurrentApprovalAmount", "sum"),
        forgiveness_records=("forgiveness_recorded", "sum"),
    )
    .reset_index()
    .sort_values(["approved_amount", "loans"], ascending=False)
)

state_summary.to_csv("ppp_813110_state_summary.csv", index=False)
print("NAICS 813110 loans: " + str(len(religious)))
print(state_summary.head(10).to_string(index=False))

# Loan status, forgiveness fields, and missing values describe SBA records.
# They do not establish fraud, tax status, or church identity.

The output is a state-level table with loan counts, approved amounts, and the number of rows containing a forgiveness amount. It does not export borrower street addresses or label individual organizations. A missing forgiveness value, a charged-off status, or an unusual amount is not a fraud finding.

Individual-level assertions should come from an identified SBA, inspector-general, DOJ, SEC, or court record. Preserve the official case number, procedural posture, dates, exact identifier, and source URL rather than deriving an accusation from the public loan file.

What remains hidden

The current below-$150,000 files are loan-level, not aggregate-only. They still do not expose EINs, and some identity fields are blank or redacted. That prevents a safe automatic join to IRS recognition records: a borrower name and ZIP can nominate a private review candidate, but cannot establish that two records describe the same institution.

The public files also omit lender-level approval rates disaggregated by borrower race, income, or geography. The SBA collected this data internally but has not published it in a form that allows systematic disparate-impact analysis. Several civil rights organizations filed FOIA requests for this data; most received redacted responses under Exemption 6 (personal privacy) for the borrower demographics.

The loan officer identifier is absent. Lenders' internal underwriting records—which loan officers approved which applications, and at what approval rates for different borrower profiles—are not in the public dataset and were not required to be reported to the SBA. This makes it impossible to assess whether approvals within a given lender varied by geography, borrower demographics, or relationship.

The political dimension

PPP data became a durable opposition research tool. Journalists identified campaign donors among the largest recipients; trade groups that lobbied for expanded PPP eligibility while simultaneously benefiting from it; members of Congress whose family businesses received loans during the period when they were voting on program oversight; and sports franchises and publicly traded hotel chains that qualified under the 500-employee-per-location rule.

The congressional district analysis, enabled by the CD field, showed that the ten congressional districts receiving the most PPP dollars per capita were overwhelmingly in states with large agricultural and construction industries—sectors with historically high per-employee payroll that drove large loan calculations. Districts in lower-income urban areas, despite having more businesses shuttered by the pandemic, received less on a per-business basis in part because smaller payrolls translated to smaller loan amounts.

The SBA has not released a comprehensive post-program audit that maps political donation history against approval rates or loan amounts. That analysis remains an open research question in the public dataset.

Using the data today

Congress enacted the PPP and Bank Fraud Enforcement Harmonization Act of 2022, Public Law 117-166, creating a program-specific 10-year limitations period for criminal charges or civil enforcement actions alleging borrower fraud under PPP. The provisions are codified at 15 U.S.C. § 636(a)(36)(W) and (37)(P). This does not make every wire-fraud allegation subject to a 10-year period; each case requires its actual statute and facts.

SAM.gov exclusion records and court outcomes can change over time. Any confirmed cross-reference needs the source dates, exact entity identifier, exclusion period, and case disposition; a current exclusion does not by itself prove what was true on the loan date.

The LoanStatus field is an SBA program record, not a misconduct label. In particular, Charged Off is an accounting and servicing status and must not be presented as proof of fraud, debarment, or ineligibility.


Related writing: The mortgage map: using HMDA loan-level data to find lending disparities covers the CFPB's Home Mortgage Disclosure Act dataset—similar FOIA-forced disclosure, similar cross-reference methodology for surfacing discriminatory patterns in lending.

Related writing: The DPA database: every federal deferred prosecution agreement since 1992 covers the Duke/UVA Corporate Prosecution Registry, which tracks how DOJ resolves corporate fraud cases—including PPP-related deferred prosecution agreements that did not result in criminal conviction.