Bowmark AIdocs

The Zebra

US insurance comparison marketplace — side-by-side auto, home and renters rates from 100+ carriers, plus published rate research by state, city, vehicle,…

US insurance comparison marketplace — side-by-side auto, home and renters rates from 100+ carriers, plus published rate research by state, city, vehicle, carrier and driver history. Its state rate research is live; the quote flows are still declarations. It does NOT quote life insurance: that surface is editorial only, measured 2026-08-01 (see getLifeQuotes).

Domain: thezebra.com

Also known as: The Zebra, TheZebra, thezebra.com

Call it directly

bowmark.providers.thezebra.getStateRates(query: thezebraStateRatesQuery): Promise<thezebraStateRates>
bowmark.providers.thezebra.getStateRequirements(query: thezebraStateRequirementsQuery): Promise<thezebraStateRequirements>
bowmark.providers.thezebra.getCityRates(query: thezebraCityRatesQuery): Promise<thezebraCityRates>
bowmark.providers.thezebra.getRatesByDriverProfile(query: thezebraDriverProfileQuery): Promise<thezebraDriverProfileRates>
bowmark.providers.thezebra.getVehicleRates(query: thezebraVehicleRatesQuery): Promise<thezebraVehicleRates>
bowmark.providers.thezebra.getCarrierRates(query: thezebraCarrierRatesQuery): Promise<thezebraCarrierRates>
bowmark.providers.thezebra.getRentersQuotes(query: thezebraRentersQuotesQuery): Promise<thezebraRentersQuotes>
bowmark.providers.thezebra.getAutoQuotes(query: thezebraAutoQuotesQuery): Promise<thezebraAutoQuotes>

Functions

FunctionWhat it does
getStateRatesReturns what car insurance costs in a US state, from The Zebra's own rate research: the state average premium (6-month and monthly), the national average annual rate by year to compare it…
getStateRequirementsReturns what a US state LEGALLY REQUIRES a driver to carry, as The Zebra's state-laws pages publish it: the liability minimums as three typed whole-dollar numbers (never the "30/60/15"…
getCityRatesReturns what car insurance costs in a specific US CITY: the city's average 6-month premium, the state average this page compares it against, the per-carrier breakdown with the cheapest…
getRatesByDriverProfileReturns how a driver's own circumstances move the premium, which is the question a state or city AVERAGE cannot answer: what each accident, claim or violation costs (21-23 incidents per…
getVehicleRatesReturns what it costs to insure one specific vehicle, from The Zebra's own rate research: the average annual premium PER MODEL YEAR and PER CARRIER with the cheapest of each year called…
getCarrierRatesReturns what ONE named insurance company charges, which is the question a state or city average cannot answer: the carrier's own national average 6-month premium, the national benchmark The…
getRentersQuotesReturns REAL renters insurance quotes for one address — each carrier's own monthly premium, total premium, deductible, and its personal-property, personal-liability, medical-expenses and…
getAutoQuotesReturns REAL auto insurance quotes for one driver and one vehicle at a US ZIP — each carrier's own monthly and six-month premium, deductible, and the coverage it priced, as The Zebra's auto…

Types

interface thezebraStateRatesQuery {
  state: string   // postal code ("CA") or name ("California"); "DC" accepted
}

interface thezebraCarrierStateRate {
  carrier: string
  liabilitySixMonth: number | null      // minimum coverage, USD per 6-month policy
  fullCoverageSixMonth: number | null   // full coverage, USD per 6-month policy
}

interface thezebraAnnualAverage {
  year: number
  averagePremium: number | null   // USD per YEAR, as the site printed it
}

interface thezebraStateRates {
  state: string                 // as The Zebra prints it, e.g. "Washington, D.C."
  stateCode: string
  asOf: string | null           // ISO-8601, the state page's own last-updated date
  averageSixMonthPremium: number | null
  averageMonthlyPremium: number | null
  nationalAverageAnnualByYear: thezebraAnnualAverage[]
  averageAnnualPremiumByYear: thezebraAnnualAverage[]
  byCarrier: thezebraCarrierStateRate[]        // cheapest full coverage first
  cheapestLiability: thezebraCarrierStateRate | null
  cheapestFullCoverage: thezebraCarrierStateRate | null
  indexUrl: string
  carrierRatesUrl: string | null
}

interface thezebraStateRequirementsQuery {
  state: string   // same jurisdiction set as thezebraStateRatesQuery
}

interface thezebraCoverageRequirement {
  coverage: string        // as the site names it, e.g. "Bodily injury per person"
  amount: number | null   // USD. null = not ONE figure (a menu of options), read text
  text: string            // the site's own wording; never null
}

interface thezebraOptionalCoverage {
  name: string
  description: string
}

interface thezebraPenalty {
  offense: string | null           // "1st offense" … ; null = page does not break it down
  reinstatementFee: number | null  // USD, only when the page tabulates it as its own column
  text: string                     // the penalty as stated; never null
}

interface thezebraStateRequirements {
  state: string
  stateCode: string
  asOf: string | null      // ISO-8601, the laws page's own last-updated date
  // The liability triple in WHOLE DOLLARS, never the "30/60/15" string.
  // null = THE STATE DOES NOT REQUIRE IT AT ALL — not zero. Florida requires no
  // bodily-injury liability whatsoever and prints its notation as "—/—/10".
  bodilyInjuryPerPerson: number | null
  bodilyInjuryPerAccident: number | null
  propertyDamage: number | null
  liabilityFormat: string | null   // the site's own notation, verbatim; the audit trail
  noFault: boolean                 // true only when the page says so in its own words
  requiredCoverages: thezebraCoverageRequirement[]   // incl. PIP/PPI a triple cannot express
  optionalCoverages: thezebraOptionalCoverage[]      // where uninsured-motorist is answered
  penalties: thezebraPenalty[]
  url: string
}

interface thezebraCityRatesQuery {
  city: string    // "Austin", "St. Paul" — both St./Saint and Ft./Fort spellings resolve
  state: string   // REQUIRED: three states publish a Springfield, so a city alone names no page
}

interface thezebraCityCarrierRate {
  carrier: string
  // WHICH of these three is populated is set by carrierRateBasis, never all three.
  fullCoverageSixMonth: number | null   // splitByCoverage pages only, USD / 6-month policy
  minimumSixMonth: number | null        // splitByCoverage pages only
  averageSixMonth: number | null        // blendedAverage pages only — NOT a full-coverage price
}

interface thezebraCityIncidentRate {
  incident: string                       // the site's own wording: "DUI", "One comp claim"
  averageSixMonthPremium: number | null
  increase: number | null                // USD over a clean record; null where only a % is printed
}

interface thezebraCityRates {
  city: string                  // as the page's own <h1> prints it
  state: string
  stateCode: string
  asOf: string | null           // the page's last-updated date; city pages vary by >6 months
  averageSixMonthPremium: number | null
  averageMonthlyPremium: number | null        // only where the page prints it; never divided out
  stateAverageSixMonthPremium: number | null  // this page's own state comparison figure
  carrierRateBasis: "splitByCoverage" | "blendedAverage" | null
  byCarrier: thezebraCityCarrierRate[]        // cheapest first, by whichever figure the basis fills
  cheapestFullCoverage: thezebraCityCarrierRate | null   // null on a blendedAverage page
  cheapestMinimum: thezebraCityCarrierRate | null        // null on a blendedAverage page
  cheapestAverage: thezebraCityCarrierRate | null        // null on a splitByCoverage page
  byIncident: thezebraCityIncidentRate[]      // [] is real: not every page publishes it
  url: string                   // which spelling actually answered
}

interface thezebraDriverProfileQuery {
  state: string   // postal code ("CA") or name ("California"); "DC" accepted
  city?: string   // OPTIONAL, and the only way to reach the age and credit axes
}

// The same fact on both page families, so the same type — an incident row is an
// incident row whether the page it came from is a state's or a city's.
type thezebraIncidentRate = thezebraCityIncidentRate

interface thezebraCarrierAccidentRate {
  carrier: string
  cleanRecordSixMonth: number | null
  afterAtFaultAccidentSixMonth: number | null
  increaseAfterAtFaultAccident: number | null   // the difference, only where both are published
}

interface thezebraAgeBracketRate {
  ageBracket: string                     // "Teenagers", "20s" … "70s"
  averageSixMonthPremium: number | null
  cheapestCompanies: string | null       // only where the page names it
}

interface thezebraCreditTierRate {
  creditTier: string                     // "Very Poor" … "Exceptional"
  averageSixMonthPremium: number | null
}

interface thezebraDriverProfileRates {
  state: string
  stateCode: string
  city: string | null                    // null when no city was asked for
  asOf: string | null                    // the STATE page's date — not a claim about the city axes
  cleanRecordSixMonthPremium: number | null   // the "None" baseline; null where omitted
  // ALWAYS state-level, including on a city call: the city pages publish a
  // thinner table (3-5 rows vs 21-23) which getCityRates returns as its own
  // byIncident. Same field name, two granularities, on purpose.
  byIncident: thezebraIncidentRate[]
  byCarrierAfterAccident: thezebraCarrierAccidentRate[]
  byAgeBracket: thezebraAgeBracketRate[]      // CITY-ONLY; [] without a city or on a bare template
  byCreditTier: thezebraCreditTierRate[]      // CITY-ONLY, and stricter — see the summary
  warnings: string[]                          // always present; says which axes were unavailable
  urls: string[]                              // every page this answer was read from
}

interface thezebraVehicleRatesQuery {
  make: string    // as a person writes it: "Toyota", "Mercedes-Benz", "MINI"
  model: string   // "RAV4", "Model 3", "Prius c". A TRIM is not a page: "RAV4 Hybrid" is, "RAV4 XLE" is not
  year?: number   // omit for every model year published; a year the site lacks THROWS
}

interface thezebraVehicleCarrierRate {
  carrier: string
  averageAnnualCost: number | null   // USD per YEAR — NOT the 6-month term the rest of this provider returns
}

interface thezebraVehicleYearRates {
  year: number
  byCarrier: thezebraVehicleCarrierRate[]   // in the site's own cheapest-first order
  cheapest: thezebraVehicleCarrierRate | null
}

interface thezebraVehicleStateRate {
  state: string
  stateCode: string | null              // null = a row whose state name we do not have a code for
  averageAnnualPremium: number | null   // USD per YEAR, this model in this state
}

interface thezebraVehicleRates {
  make: string                          // as the page's own <h1> names it
  model: string
  driverProfile: string | null          // the page's own sentence saying WHICH DRIVER these price
  averageMonthlyCost: number | null     // the model's headline figure, USD per MONTH
  vehicleClass: string | null           // the body style compared against: "SUVs", "sedans"
  classAverageMonthlyCost: number | null   // what that class averages, USD per MONTH
  byYear: thezebraVehicleYearRates[]    // newest model year first
  byState: thezebraVehicleStateRate[]   // [] on most models — not an error; read warnings
  warnings: string[]
  url: string
}

interface thezebraCarrierRatesQuery {
  carrier: string   // "GEICO", "State Farm" — matched against the site's own 81-carrier roster
}

interface thezebraCarrierCompetitorRate {
  carrier: string
  // WHICH group is populated is set by carrierRateBasis, never both.
  liabilitySixMonth: number | null       // splitByCoverage only, USD / 6-month policy
  fullCoverageSixMonth: number | null    // splitByCoverage only
  averageMonthlyPremium: number | null   // blendedMonthly only — a MONTHLY figure
}

interface thezebraCarrierAgeRate {
  ageBracket: string                     // the site's own wording: "Teens", "20s" … "60s"
  averageMonthlyPremium: number | null   // MONTHLY, as that template publishes it
}

interface thezebraCarrierRates {
  carrier: string                            // the site's own spelling, e.g. "GEICO"
  asOf: string | null                        // ISO-8601, the review's own dateModified
  // The template-independent pair, from the page's own comparison sentence.
  averageSixMonthPremium: number | null      // THIS carrier's national average
  nationalAverageSixMonthPremium: number | null   // the benchmark it is stated against
  carrierRateBasis: "splitByCoverage" | "blendedMonthly" | null
  byCarrier: thezebraCarrierCompetitorRate[] // includes this carrier; [] is real
  cleanRecordSixMonthPremium: number | null  // the claims table's "None" baseline
  byIncident: thezebraIncidentRate[]         // what THIS carrier charges after a claim
  byAgeBracket: thezebraCarrierAgeRate[]     // [] is real
  warnings: string[]                         // always present; says which axes were unavailable
  url: string
}

// The renter this quote prices. Deliberately NARROWER than the usual quote
// identity: The Zebra's renters funnel says on its own contact page "We won't ask
// for your phone number!", so this function takes none.
interface thezebraRentersApplicant {
  firstName: string
  lastName: string
  dob: string     // ISO YYYY-MM-DD — carriers rate on the DATE, not on an age
  email: string
}

interface thezebraRentersQuotesQuery {
  address: { street: string; city: string; state: string; zip: string }  // state is a 2-letter code
  applicant: thezebraRentersApplicant
  livedHereFiveYears?: boolean   // the funnel's own question; default true
}

interface thezebraRentersCoverage {
  name: string           // the site's own label, e.g. "Personal Property"
  value: string          // verbatim, e.g. "$5k" — not every row is money ("Covered")
  amount: number | null  // parsed: "$5k" -> 5000, "12 months" -> 12
}

interface thezebraRentersQuote {
  carrier: string                       // e.g. "Liberty Mutual"
  carrierSlug: string                   // the site's own slug, e.g. "liberty-mutual"
  monthlyPremium: number                // USD per MONTH; the card's period is asserted
  totalPremium: number | null           // USD for the whole term, never derived
  policyLengthMonths: number | null
  deductible: number | null
  personalPropertyLimit: number | null
  personalLiabilityLimit: number | null
  medicalExpensesLimit: number | null
  lossOfUseLimit: number | null
  coverages: thezebraRentersCoverage[]  // every row the card publishes
}

interface thezebraRentersQuotes {
  quotes: thezebraRentersQuote[]     // cheapest monthly premium first; [] is a real answer
  // The carriers ADVERTISED beside the quotes — paid placements with no price.
  // Returned under their own name so they can never be read as offers.
  advertisedCarriers: string[]
  warnings: string[]
  url: string
}

interface thezebraAutoDriver {
  firstName: string
  lastName: string
  dob: string     // ISO YYYY-MM-DD — carriers rate on the DATE, not on an age
  email: string
  ageFirstLicensed?: number  // default 16 when omitted
  violations?: { accidents: number, claims: number, tickets: number }  // default a clean record
  occupation?: string  // default "OTHER" — the only two confirmed-valid values are "OTHER" and "ENGINEER"
  residenceOwnership?: 0 | 1 | 2 | 3  // own home/condo/rent/other; default 3 ("Other")
}

interface thezebraAutoVehicle {
  year: number    // 4-digit; a model year The Zebra does not rate THROWS
  make: string    // "Toyota", "Tesla"
  model: string   // "Camry", "Model 3" — a TRIM is not a page
}

interface thezebraAutoQuotesQuery {
  driver: thezebraAutoDriver
  vehicle: thezebraAutoVehicle
  state: string   // 2-letter postal code
  zip: string     // 5 digits
  county: string  // the county the ZIP sits in — the gateway validates server-side
  currentlyInsured?: boolean         // default true
  userPurchaseTimeframe?: "TODAY" | "FUTURE"  // default "TODAY"
}

interface thezebraAutoQuote {
  carrier: string                       // e.g. "Progressive"
  carrierSlug: string                   // the site's own slug, e.g. "progressive"
  monthlyPremium: number                // USD per MONTH; the card's period is asserted
  sixMonthPremium: number | null        // USD per 6-month policy, where the card publishes one
  totalPremium: number | null           // USD for the whole term, never derived
  policyLengthMonths: number | null
  deductible: number | null
  coverages: string[]                   // every coverage the card lists, verbatim
}

interface thezebraAutoQuotes {
  quotes: thezebraAutoQuote[]           // cheapest monthly premium first; [] is a real answer
  // The carriers ADVERTISED beside the quotes — paid placements with no price.
  // Returned under their own name so they can never be read as offers.
  advertisedCarriers: string[]
  warnings: string[]                    // names every dropped source / what the gateway refused
  url: string
}