openapi: 3.2.0 info: title: Crust Search API version: 2.0.0 description: Self-scraped Google and public LinkedIn data as a clean JSON API. servers: - url: https://crustapi.com security: - ApiKeyAuth: [] tags: - name: Search paths: /v1/search: get: operationId: search summary: Query any Google surface description: 'One endpoint for the whole Google menu. Set `type` to choose the surface (default `web`). Each type returns a serper-compatible shape under its own key: web/scholar/patents/lens -> `organic`; news -> `news`; shopping -> `shopping`; images -> `images`; videos -> `videos`; maps/places -> `places`; reviews -> `reviews`; autocomplete -> `suggestions`; webpage -> `text` + `metadata` + `jsonld`. Billed 1 credit per successful query (Maps bills 1 credit per business returned). Blocked/empty rides are free.' parameters: - name: type in: query required: false description: Which Google surface to query. schema: type: string default: web enum: - web - maps - places - news - shopping - images - videos - reviews - scholar - patents - autocomplete - webpage - lens - name: q in: query required: false description: The search query. Required for every type EXCEPT webpage and lens (use `url`) and reviews (use `placeId` / `cid` / `fid`). schema: type: string - name: url in: query required: false description: 'type=webpage: the page URL to scrape. type=lens: the image URL for reverse image search.' schema: type: string - name: gl in: query required: false description: Country code (us, gb, de, ...). Not used by maps, patents, or webpage. schema: type: string default: us - name: hl in: query required: false description: Language code (en, es, ...). Not used by patents or webpage. schema: type: string default: en - name: page in: query required: false description: Result page. Not used by reviews, autocomplete, webpage, or lens. schema: type: integer minimum: 1 default: 1 - name: tbs in: query required: false description: Time filter for web/news/images/videos (e.g. qdr:h past hour, qdr:d past day, qdr:w past week, qdr:m past month, qdr:y past year). schema: type: string - name: num in: query required: false description: 'type=reviews: reviews per page (default 20, max 50).' schema: type: integer - name: ll in: query required: false description: 'type=maps: GPS position and zoom as @latitude,longitude,zoom.' schema: type: string - name: placeId in: query required: false description: Google place id (ChIJ...). Optional for maps; identifies the place for reviews. schema: type: string - name: cid in: query required: false description: Google customer id. Optional for maps; identifies the place for reviews. schema: type: string - name: fid in: query required: false description: Google feature id (0x..:0x..). Identifies the place for reviews. schema: type: string - name: sortBy in: query required: false description: 'type=reviews: review sort order.' schema: type: string enum: - mostRelevant - newest - highest - lowest default: mostRelevant - name: nextPageToken in: query required: false description: 'type=reviews: cursor from the previous response to fetch the next page of reviews.' schema: type: string - name: includeMarkdown in: query required: false description: 'type=webpage: also return the page rendered as Markdown.' schema: type: boolean default: false - name: location in: query required: false description: City/region hint for web and places. schema: type: string - name: limit in: query required: false description: 'type=maps only: how many businesses to return (1-100). Each is one credit.' schema: type: integer minimum: 1 maximum: 100 default: 20 - name: stars in: query required: false description: 'type=maps: include the 1-5 star rating distribution per place.' schema: type: boolean responses: '200': description: Results for the chosen surface. The populated array key depends on `type`. content: application/json: schema: $ref: '#/components/schemas/SearchResult' '400': description: Missing or invalid parameter. '401': description: Missing or invalid API key. '402': description: Out of credits. '429': description: Rate limited. '502': description: Upstream fetch failed (uncharged). '503': description: Surface temporarily unavailable, retry shortly (uncharged). tags: - Search components: schemas: NewsItem: type: object properties: title: type: string link: type: string snippet: type: - string - 'null' date: type: - string - 'null' source: type: - string - 'null' imageUrl: type: - string - 'null' position: type: integer Review: type: object properties: rating: type: integer date: type: - string - 'null' isoDate: type: - string - 'null' snippet: type: - string - 'null' likes: type: integer description: Total reactions on the review (sum across reaction types). user: type: object properties: name: type: - string - 'null' thumbnail: type: - string - 'null' link: type: - string - 'null' reviews: type: - integer - 'null' photos: type: - integer - 'null' media: type: array items: type: object properties: type: type: string imageUrl: type: string caption: type: string link: type: - string - 'null' id: type: - string - 'null' response: type: - object - 'null' description: Owner reply, when present. properties: date: type: string snippet: type: string Place: type: object description: A place. type=places returns the lean serper-parity subset; type=maps returns this full shape (contact details, categories, opening hours, attributes and photos on top). properties: position: type: integer title: type: string description: Business name. address: type: - string - 'null' latitude: type: - number - 'null' longitude: type: - number - 'null' rating: type: - number - 'null' description: Star rating out of 5. ratingCount: type: - integer - 'null' reviewsCount: type: - integer - 'null' description: 'Maps: exact review count.' reviewsDistribution: type: - object - 'null' description: 'Maps with stars=true: 1-5 star histogram.' category: type: - string - 'null' phoneNumber: type: - string - 'null' website: type: - string - 'null' cid: type: - string - 'null' placeId: type: - string - 'null' priceLevel: type: - string - 'null' description: Google's price band token, e.g. "$1–10". Null when Google shows none. thumbnailUrl: type: - string - 'null' description: A real place photo URL (maps only). bookingLinks: type: array items: type: string description: Reservation/booking URLs when the place is bookable (maps only, sparse). url: type: string description: Google Maps place URL. type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). fid: type: string description: Google feature id (0x…:0x…), usable as an input to type=reviews. type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). street: type: - string - 'null' description: Street line of the address. type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). city: type: - string - 'null' description: type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). state: type: - string - 'null' description: type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). postalCode: type: - string - 'null' description: type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). countryCode: type: - string - 'null' description: ISO country code. type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). location: type: object description: '{lat,lng}. type=maps only (the richer Maps shape; type=places returns the lean serper-parity set).' properties: lat: type: number lng: type: number phone: type: - string - 'null' description: Formatted phone number. Null when Google does not show one. type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). phoneUnformatted: type: - string - 'null' description: E.164-style phone number. type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). categoryName: type: - string - 'null' description: Primary Google category. type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). categories: type: array items: type: string description: All Google categories. type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). totalScore: type: - number - 'null' description: Average star rating (same value as rating). type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). description: type: - string - 'null' description: Google's editorial summary when present. type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). openingHours: type: object additionalProperties: type: string description: Day name to hours string, e.g. {"Monday":"7:30 AM-2 PM"}. type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). permanentlyClosed: type: boolean description: type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). mainImage: type: - string - 'null' description: Primary place photo. type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). attributes: type: object additionalProperties: type: array items: type: string description: Google's attribute groups, e.g. {"Service options":["Takeout"]}. type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). scrapedAt: type: string format: date-time description: When this record was collected. type=maps only (the richer Maps shape; type=places returns the lean serper-parity set). ImageItem: type: object properties: title: type: string imageUrl: type: string imageWidth: type: - integer - 'null' imageHeight: type: - integer - 'null' thumbnailUrl: type: string thumbnailWidth: type: - integer - 'null' thumbnailHeight: type: - integer - 'null' source: type: - string - 'null' description: The publisher's display name as Google shows it. domain: type: - string - 'null' link: type: - string - 'null' googleUrl: type: - string - 'null' position: type: integer creator: type: string description: Image creator from IPTC metadata (sparse — only when Google carries it). copyright: type: string description: Copyright notice from IPTC metadata (sparse). SearchResult: type: object description: Polymorphic result. `searchParameters` echoes your request; the populated array key depends on `type`. properties: searchParameters: type: object additionalProperties: true organic: type: array description: web, scholar, patents, lens items: $ref: '#/components/schemas/OrganicResult' places: type: array description: maps, places items: $ref: '#/components/schemas/Place' news: type: array items: $ref: '#/components/schemas/NewsItem' shopping: type: array items: $ref: '#/components/schemas/ShoppingItem' images: type: array items: $ref: '#/components/schemas/ImageItem' videos: type: array items: $ref: '#/components/schemas/VideoItem' reviews: type: array items: $ref: '#/components/schemas/Review' suggestions: type: array items: $ref: '#/components/schemas/Suggestion' text: type: string description: 'type=webpage: the page''s readable text.' markdown: type: string description: type=webpage with includeMarkdown=true. metadata: type: object description: 'type=webpage: title + og/twitter/article meta.' additionalProperties: true jsonld: description: 'type=webpage: parsed JSON-LD.' nextPageToken: type: string description: 'type=reviews: cursor for the next page.' creditsRemaining: type: - integer - 'null' tookMs: type: integer OrganicResult: type: object description: Web / Scholar / Patents / Lens result. properties: title: type: string link: type: string snippet: type: - string - 'null' date: type: - string - 'null' position: type: integer source: type: - string - 'null' description: Scholar publication info / Lens source site. citedBy: type: - integer - 'null' description: Scholar. assignee: type: - string - 'null' description: Patents. filingDate: type: - string - 'null' description: Patents. imageUrl: type: - string - 'null' description: Lens. thumbnailUrl: type: - string - 'null' description: 'Lens: thumbnail of the matched image.' publicationInfo: type: - string - 'null' description: 'Scholar: authors, journal and year as one line.' year: type: - integer - 'null' description: 'Scholar: publication year parsed from publicationInfo.' pdfUrl: type: - string - 'null' description: 'Scholar: link to the PDF copy when one is offered.' id: type: - string - 'null' description: 'Scholar: Google Scholar cluster id for the result.' htmlUrl: type: - string - 'null' description: 'Scholar: full-text link when the side resource is an HTML copy (pdfUrl is null then).' ShoppingItem: type: object properties: title: type: string source: type: - string - 'null' condition: type: - string - 'null' link: type: - string - 'null' description: Google product page URL (always present since 2026-08). price: type: - string - 'null' imageUrl: type: - string - 'null' description: 'Product thumbnail: a gstatic URL, or an inline data:image URI for some top-of-page rows.' rating: type: - number - 'null' ratingCount: type: - integer - 'null' productId: type: - string - 'null' position: type: integer VideoItem: type: object properties: title: type: string link: type: string snippet: type: - string - 'null' imageUrl: type: - string - 'null' duration: type: - string - 'null' source: type: - string - 'null' channel: type: - string - 'null' date: type: - string - 'null' position: type: integer Suggestion: type: object properties: value: type: string securitySchemes: ApiKeyAuth: type: apiKey in: header name: x-api-key