Quickstart
Prefer no code? Open the dashboard to run requests and download results.
Using the API? Get your API key and replace key_live_xxxx below. You get $6 of free usage each month, no card required.
Refresh current details for a LinkedIn profile URL.
curl "https://crustapi.com/v1/linkedin?type=refresh&url=https%3A%2F%2Fwww.linkedin.com%2Fin%2Fdharmesh" \ -H "x-api-key: key_live_xxxx"
{
"publicIdentifier": "dharmesh",
"accessible": true,
"profileState": "accessible",
"firstName": "Dharmesh",
"lastName": "Shah",
"headline": "Founder and CTO at HubSpot. Helping millions grow better.",
"currentTitle": "Founder and CTO",
"titleSource": "headline",
"currentCompany": {
"name": "HubSpot",
"slug": "hubspot",
"linkedInUrl": "https://www.linkedin.com/company/hubspot",
"linkedInId": "68529"
},
"currentSchool": {
"name": "Massachusetts Institute of Technology",
"slug": "mit",
"linkedInUrl": "https://www.linkedin.com/school/mit",
"linkedInId": "1503"
}
}
Selected fields from recorded responses. Long text is shortened and phone numbers are masked. Live results can differ. Full field references are below.
Response fields
Pricing and billing
Your account uses a prepaid USD balance. Every eligible account gets $6 of free usage each month, including accounts with paid funds. Paid deposits never expire. Free usage resets on the date shown in Billing.
| Deposit | Google Search / 1,000 requests | Maps / 1,000 businesses | LinkedIn Profiles / 1,000 | LinkedIn Companies / 1,000 | LinkedIn Posts / 1,000 requests | People, Jobs, Refresh / 1,000 units |
|---|---|---|---|---|---|---|
| $10+ | $1.00 | $1.96 | $4.00 | $3.00 | $6.00 | $1.96 |
| $149.00+ | $0.76 | $1.49 | $3.00 | $2.50 | $4.50 | $1.49 |
| $549.00+ | $0.56 | $1.10 | $2.50 | $2.00 | $3.30 | $1.10 |
| $1,999.00+ | $0.41 | $0.80 | $2.00 | $1.75 | $2.45 | $0.80 |
| $6,500.00+ | $0.33 | $0.65 | $1.75 | $1.60 | $1.95 | $0.65 |
| $27,500.00+ | $0.28 | $0.55 | $1.60 | $1.50 | $1.65 | $0.55 |
| $50,000.00+ | $0.26 | $0.50 | $1.50 | $1.50 | $1.50 | $0.50 |
| $100,000.00+ | $0.20 | $0.40 | $1.50 | $1.50 | $1.50 | $0.40 |
Each deposit qualifies separately and keeps its saved prices until spent. Deposits do not accumulate into a permanent account tier. Free funds are spent first, then the paid funds with the lowest applicable endpoint rate, oldest first when rates tie.
Google Search, LinkedIn Person, Company, Posts, People and Jobs are billed per successful request. Maps is billed per business returned. People with enrich=true uses the LinkedIn read rate per full profile returned. Refresh uses the LinkedIn search rate per accessible profile. Work email lookup is included. Empty and failed responses cost zero.
Wallet responses add billing.chargedUsd and billing.remainingUsd as decimal strings. GET /v1/balance returns wallet.availableUsd, available funds and saved prices. Existing numeric credits, charged and creditsRemaining fields remain numeric; for a wallet, the remaining-credit compatibility value is an affordable-unit count, not dollars. It can differ by endpoint. Use the explicit USD fields for accounting.
Dashboard estimates use your current available funds and saved prices. Actual charges depend on successful results and funds available when the request completes. Concurrent requests or a free-allowance reset can change the next applicable rate. Your activity log records the actual charge.
Existing purchased usage is preserved at the better of its old and applicable new endpoint prices. An account still showing credits keeps its current terms until it is converted. The separate x402 agent-credit path below retains its stated credit terms.
Refresh people records, read profiles and companies, or search people, posts and jobs. All LinkedIn data comes from public, logged-out sources.
People database refresh
Send the LinkedIn URLs you already have. Refresh returns available current employers, company and school IDs, names, headline/title data, photo and profile status. Compare the response with your stored record to identify changes.
Refresh fields are at the response root. Use batch requests for a list, or try Refresh in the app. For employment history and other profile sections, use type=person.
Refresh response fields
| Field | Meaning |
|---|---|
url | Requested LinkedIn URL. |
publicIdentifier | Public profile handle from the LinkedIn URL. |
resolvedUrl | Confirmed profile URL when available. Renamed URLs are not automatically discovered. |
firstName | Published first name. |
lastName | Published last name. |
headline | Published profile headline. It is not necessarily a job title. |
headlineSource | Source label for the returned headline. |
currentTitle | Current role title when supported by the available data. See titleSource for its basis. |
titleSource | headline means the title comes from headline wording; linkedin means an explicit role title. |
currentCompany | Current employer object: name, slug, linkedInUrl and linkedInId when available. Numeric IDs are strings; missing values can be null. |
currentSchool | Published school object: name, slug, linkedInUrl and linkedInId when available. Numeric IDs are strings; missing values can be null. |
accessible | Whether public profile data was returned. |
profileState | Profile URL status. See the profile-status reference below. |
companyState | Employer availability: public, restricted, not_published or unknown. Missing data does not prove a job change. |
photo | Public profile photo URL, or null when unavailable. |
photoState | Availability label for the profile photo. |
memberIdentifier | Numeric member ID as a string, when available. Refresh requires member=true, which can increase response time. |
memorialized | True when a public memorialization marker is established; otherwise null. Null does not establish account activity or whether the person is alive. |
memorializedSource | Source label for a returned memorialization marker. |
tookMs | Request processing time in milliseconds. |
creditsRemaining | Numeric balance compatibility value. For wallet dollar amounts, use billing.remainingUsd. |
billing | Wallet charge and balance as decimal strings in chargedUsd and remainingUsd, when applicable. |
Choose a LinkedIn operation
| type | What you get |
|---|---|
refresh | Current public details for a profile URL. |
person, profile | Public profile, employment, education and additional sections when available. Returned under profile. |
company | Company details, offices, related pages, featured products and public contacts. Returned under company. |
people, search | People matching names, professions or filters. Returned in people. |
posts | Recent public posts from a person or company URL, returned in posts. |
job, jobs | A job URL returns one job; keywords or filters return job search results. Both use the jobs key. Search results may have fewer fields than a job detail. |
Fields vary by profile and operation. Null values and empty sections mean the information was not returned; they do not prove it does not exist. The OpenAPI reference describes the response structures.
Person response fields
| Field | Meaning |
|---|---|
id | Profile identifier. |
name | Published full name. |
firstName | Published first name. |
lastName | Published last name. |
publicIdentifier | Public profile handle from the LinkedIn URL. |
linkedinUrl | Public LinkedIn URL. |
memberId | Numeric LinkedIn member ID as a string, when available. |
memberIdentifier | Numeric member ID as a string, when available. Refresh requires member=true, which can increase response time. |
linkedInIdentifier | LinkedIn member URN, when available. |
headline | Published profile headline. It is not necessarily a job title. |
headlineSource | Source label for the returned headline. |
currentTitle | Current role title when supported by the available data. See titleSource for its basis. |
titleSource | headline means the title comes from headline wording; linkedin means an explicit role title. |
about | Published About text. |
currentCompany | Current employer name. This is a string; Refresh uses a company object. |
currentCompanyId | Numeric current-company ID as a string, when available. |
currentSchoolId | Numeric school ID as a string, when available. |
companyState | Employer availability: public, restricted, not_published or unknown. Missing data does not prove a job change. |
currentCompanyDomain | Current employer’s website domain, when available. |
currentCompanyIndustry | Current employer’s industry, when available. |
currentCompanySize | Current employer’s size band, when available. |
currentCompanyHeadquarters | Current employer’s headquarters, when available. |
location | Location object with published text and available parsed components. |
city | City name, when available. |
state | State or region, when available. |
country | Country name, when available. |
countryCode | Two-letter country code, when available. |
experience | Available employment rows. Missing end dates do not establish that a role is current. |
experienceState | Availability label for the returned employment history. |
experienceAvailability | Counts of returned employment rows. positionsWithTitle and positionsWithDerivedTitle count explicit and derived titles separately; this does not establish complete history. |
education | Available education rows with schools, qualifications and dates. |
skills | Available published skills. |
languages | Available published languages. |
certifications | Available certifications and their details. |
courses | Available published courses. |
volunteering | Available volunteer experience. |
organizations | Available organization memberships and roles. |
publications | Available publications and supporting details. |
projects | Available projects and supporting details. |
honorsAndAwards | Available honors and awards. |
recommendations | Available recommendation entries. These may be a subset of the reported count. |
recommendersCount | Reported recommendation count, when available. |
peopleAlsoViewed | Available related profiles. |
followerCount | Reported follower count, when available. |
followers | Alias of followerCount. |
connectionsCount | Reported connection count, when available. |
connections | Alias of connectionsCount. |
websites | Published links as objects containing url and label. |
website | Existing single-website field. Additional links appear in websites. |
photo | Public profile photo URL, or null when unavailable. |
photoState | Availability label for the profile photo. |
bannerImage | Public profile background image URL, when available. |
coverPhoto | Alias of bannerImage. |
influencer | Public influencer marker when established; null means unknown. |
topVoice | Public Top Voice marker when established; null means unknown. |
creator | Public creator marker when established; null means unknown. |
memorialized | True when a public memorialization marker is established; otherwise null. Null does not establish account activity or whether the person is alive. |
memorializedSource | Source label for a returned memorialization marker. |
workEmail | Work email when available with email=true. Check emailStatus before use. |
emailStatus | Work-email status. pattern-likely is unverified and is not equivalent to verified. |
emailConfidence | Confidence value associated with the returned work email. |
companyDomain | Employer domain associated with the email lookup. |
publicHeadline | Optional additional headline field requested with headline=true. |
Employment rows can include title, employer name/URL/ID, location, description, dates, logo and provenance. Education rows can include school name/URL/ID, degree, field of study, dates, description and logo. experienceAvailability counts returned rows only.
Company response fields
| Field | Meaning |
|---|---|
name | Published company name. |
universalName | Company handle from its LinkedIn URL. |
linkedInId | Numeric LinkedIn company ID as a string. |
linkedinUrl | Public LinkedIn URL. |
pageType | Company or showcase page type. |
tagline | Published company tagline. |
description | Published company description. |
website | Published website URL, when available. |
industry | Published industry. |
companyType | Published organization type. |
founded | Published founding year, when available. |
specialties | Published company specialties. |
companySize | Published employee size band. |
employeeCountRange | Numeric lower and upper bounds of the published size band. |
employeeCount | Employee count reported by LinkedIn. This can differ from the size band. |
followers | Follower count, when available. |
headquarters | Published headquarters location. |
address | Structured headquarters address, when available. |
locations | Published offices. Rows may include addressLines, directionsUrl and isPrimary; a map link does not establish coordinates. |
logo | Public company logo URL. |
banner | Public company banner URL. |
crunchbaseUrl | Published Crunchbase link, when available. |
similarCompanies | Available related company pages. |
affiliatedPages | Available affiliated company or showcase pages. An affiliation does not necessarily mean a subsidiary. |
employeeSample | Partial public employee sample with names and profile URLs. It is not a complete workforce list. |
employees | Additional matching-people results with employees=true. These are returned separately from the company object and are not a complete workforce list. |
publishedContacts | Published emails and phone numbers with supporting text and URL. Publication does not verify ownership or reachability. |
employeeSearchCompanyIds | Company IDs associated with employee search. These do not replace the company’s own linkedInId. |
jobSearchUrl | Company jobs link, when available. It is not a vacancy count. |
featuredProducts | Available featured products with names, links and details. This may be a selection of all products. |
Jobs, posts and people search
Jobs can return title, company name/URL, location, description, seniority, employment type, functions, industries, salary and status. jobPoster contains a published contact’s name, headline and URL. Optional fields include datePosted, validThrough, educationRequirements, experienceRequirements, jobLocation, sourceJobIdentifier and jobMetadataSource. A missing company URL does not remove the company name. validThrough is a published validity date, not confirmed closure.
Posts include available text, date, link, author, images, reactions and comment counts. comments=true adds available comments. People search returns available identity, location, employer, education and audience counts. Inspect source, returned, totalAvailable and totalCapped when present; a total may be capped and results are not guaranteed to cover every match.
Profile status and missing values
| profileState | Meaning |
|---|---|
accessible | Public data was returned. |
exists_not_public | The profile is recognized, but public data is unavailable. Exact account settings are unknown. |
not_resolvable | This URL did not resolve to a profile. It does not prove permanent deletion. |
unknown | The profile state could not be established. Keep your previous record and retry later. |
Keep existing values when new information is unavailable or uncertain. Missing employer data does not prove someone left a job. Unavailable Profile and Refresh results are not charged.
LinkedIn request parameters
| Parameter | Usage |
|---|---|
url | Profile URL for Refresh/person, company URL for company, person/company URL for posts, or job URL for job. |
member | Refresh: member=true adds the numeric member ID when available. |
keywords | Search text for people or jobs. Supported filters can also be used without keywords. |
location | People or job location. For jobs, separate up to three locations with semicolons. |
company | People: current employer. Jobs: company name, LinkedIn company URL or numeric ID. |
school | School filter for people search. |
title | Profession filter for people search. Combine with location; unsupported professions can return no results. |
profession | Alias of the people-search title filter. |
industry | Industry filter for people search. |
companySize | Employer size filter for people search. |
pastCompany | Previous-employer filter for people search. |
followersMin | Minimum follower count for people search. |
followersMax | Maximum follower count for people search. |
connectionsMin | Minimum connection count for people search. |
connectionsMax | Maximum connection count for people search. |
expCountMin | Minimum employment-row count for people search. |
expCountMax | Maximum employment-row count for people search. |
titleExclude | Exclude titles from people or job searches. Comma-separate multiple values. |
companyExclude | Exclude employers from people search. Comma-separate multiple values. |
locationExclude | Exclude locations from people or job searches. Semicolon-separate multiple locations. |
pastCompanyExclude | Exclude previous employers from people search. Comma-separate multiple values. |
sortBy | Jobs: newest first by default; use relevance for relevance order. |
postedWithin | Jobs: 24h, week or month publication window. |
daysSincePostedMin | Jobs: minimum days since posting. |
daysSincePostedMax | Jobs: maximum days since posting. |
employmentType | Jobs: comma-separated employment types, such as Full-time,Contract. |
seniority | Jobs: comma-separated seniority levels, such as Director,Executive. |
titleInclude | Jobs: comma-separated terms to match in the title. |
descriptionKeywords | Jobs: comma-separated terms to match in the title or description. |
hasRecruiter | Jobs: true requires a published job poster; false excludes those postings. |
count | People/jobs: count=true returns a free count preview without rows. Counts can be unavailable or capped; check the returned metadata. |
num | Requested result count. Jobs default to 25 (max 100); posts to 50 (max 100). People limits depend on search type. |
limit | Alternative result-count parameter. Jobs default to 25 (max 100); posts to 50 (max 100). People limits depend on search type. |
start | Result offset for supported searches. |
email | Person/profile: email=true adds work-email fields when available. |
domain | Known employer domain for the person/profile email lookup. |
companyId | Person/profile: true requests the first returned company’s numeric ID. Other rows may already include IDs. |
schoolId | Person/profile: true requests the first returned school’s numeric ID. Other rows may already include IDs. |
headline | Person/profile: headline=true requests the optional publicHeadline field. |
employees | Company: employees=true adds matching-people results. |
comments | Posts: comments=true adds available comments. |
enrich | People/search: enrich=true adds available full profiles, billed per profile returned. |
Billing
Person, Company, Posts, People and Jobs each use their endpoint’s rate per successful request. People with enrich=true bills per full profile returned. Refresh bills per accessible profile. Work email lookup is included; a successful profile is billable even if no email is found. See current prices.
One endpoint, one parameter that picks the Google surface. Change type, keep everything else the same.
The surfaces you can ask for:
| type | what you get |
|---|---|
maps | Local businesses: name, address, phone, website, rating, review count |
web | Google web search: organic results, people-also-ask, related searches |
places | Local place results in a compact response |
news | Google News: title, source, date, and a real hero image |
shopping | Google Shopping products with prices and sellers |
images | Google Images results |
videos | Google Videos with direct thumbnails |
scholar | Google Scholar papers and citations |
patents | Google Patents results |
autocomplete | Google autocomplete suggestions for a query |
webpage | Any URL as clean text, metadata, and JSON-LD, ready to feed an AI (RAG) |
lens | Reverse image search: pass an image url and get visual matches with titles and links. Country and language filters do not apply to Lens. |
reviews | Google reviews for a business, with sorting and pagination |
Google Maps response fields
For type=maps, businesses are returned in places. Field availability varies by listing, category and country. A missing phone or website stays empty.
Maps field reference
| Field | Meaning |
|---|---|
position | Business position in the returned results. |
title | Business name. |
placeId | Google place identifier. |
fid | Google feature identifier. |
cid | Google customer identifier for the listing. |
url | Google Maps link for the listing. |
address | Formatted business address. |
street | Street address, when available. |
city | City name, when available. |
state | State or region, when available. |
postalCode | Postal or ZIP code, when available. |
countryCode | Two-letter country code, when available. |
location | Coordinates as an object containing lat and lng. |
phone | Published phone number in local format. |
phoneUnformatted | Published phone number with country code, when available. |
website | Published website URL, when available. |
categoryName | Primary business category. |
categories | Available business categories. |
description | Published listing description, when available. |
totalScore | Average star rating, when available. |
reviewsCount | Total review count, when available. |
reviewsDistribution | Counts from oneStar through fiveStar with stars=true (alias details=true), when available. This option can increase response time. |
openingHours | Published opening hours by day. |
priceLevel | Published price range or level, when available. |
permanentlyClosed | Permanent-closure flag when returned. |
mainImage | Lead listing image URL, when available. |
thumbnailUrl | Listing thumbnail URL, when available. |
bookingLinks | Available booking links. |
attributes | Available business attributes. |
scrapedAt | Collection timestamp for the listing. |
Common parameters
| param | what it does |
|---|---|
q | Your search query. Required for most surfaces. |
gl | Country code, like us or gb. |
hl | Language code, like en. |
location | Where to search from, for maps and places, like Miami, FL. |
limit | For type=maps: how many businesses to return. Default 20, max 100. |
num | For type=reviews: how many reviews per page. Default 20, max 50. For type=images: how many images to return. Leave it off and you get the full set, which is usually about 99. |
page | Which page of results to return. |
The full machine-readable spec lives at /v1/openapi.json. Point your tooling or your agent at it.
Freshness
Every search is fetched when you ask for it. We never return an older result in place of a failed fetch: if we cannot complete your search, you get an error, it is free, and you can retry. The one exception is small and always disclosed. If you send the same search again within 60 seconds, you may get the answer from the first one, and when that happens the response says so with "cached": true and "cacheAgeSeconds". Add &fresh=1 to force a new fetch every time.
Rate limits
Some search types take longer to fetch than others, so each key has a limit on how many of them can be in flight at the same time. Send up to the limit, wait for the responses, then send more. Requests over the limit get a 429 with a Retry-After header. If we are briefly at capacity, your request may wait a few seconds before it is served or returned as a 429. Rate-limited calls are never charged.
| plan | web, news | images, shopping, videos, scholar, lens |
|---|---|---|
| Free | 2 in flight per key | 1 in flight per key |
| Paid | 5 in flight per key | 3 in flight per key |
Maps, places, reviews, autocomplete, patents, webpage and the LinkedIn endpoints have no in-flight limit. If your project needs more than the paid limit, talk to us and we will set it up.
Bulk lists and webhooks
Send up to 100 URLs to POST /v1/linkedin/batch. Supported types are refresh, person (alias profile), company and posts. Results stay in input order, with a separate success or error for each row.
The response contains a results array. Each row includes url, ok, and data or error. data contains the operation’s payload without the single-request billing/timing envelope. Inaccessible rows are uncharged; inspect data.accessible or notAccessible when present.
Async delivery, up to 10,000 URLs
Add a public HTTPS webhook URL. The API returns HTTP 202 with a jobId, then POSTs the completed batch to your webhook. The X-Crustapi-Job header identifies the delivery.
Large result sets may be delivered as resultsUrl with resultsBytes and resultsExpireAt. Download the JSON before that expiry; the temporary file is then deleted. Save inline webhook results in your own system.
The status endpoint returns job status, counts and delivery information, not result rows. Use the same account’s API key. Webhooks must have no embedded credentials; redirects are not followed and a failed delivery is retried once.
Options: member: true for Refresh and comments: true for posts. Batch does not support employees=true. Each successfully delivered row uses the chosen endpoint’s rate; unavailable results and malformed URLs are uncharged.
CLI
Prefer the terminal? Install the CLI and get the same data from your shell, as JSON or CSV.
Output is JSON by default and pipes cleanly, the status line goes to stderr so your pipes stay clean. Pass --csv for CSV. It's on npm as crustapi-cli.
MCP for AI assistants
Give Claude Desktop, Cursor, Cline, or any MCP client Google and public LinkedIn data. With Node.js installed, npx runs it. Add this to your client config and restart it.
Four tools appear. search is the whole menu behind one call, scrape_webpage turns any URL into clean text you can feed straight to an AI (RAG), and get_reviews pulls Google reviews for a business. The package is on npm as crustapi-mcp. The fourth, linkedin, is the LinkedIn menu: profiles, companies, jobs, posts and people search.
For People Refresh, call /v1/linkedin?type=refresh through your agent’s HTTP tool. The published MCP package currently exposes profile, company, posts, jobs and people search.
Integrations
Use CrustAPI from any tool that supports HTTP requests and custom headers.
Connect with HTTP requests
Add an HTTP request step in your tool. Choose GET, enter the endpoint and query parameters below, and add your API key in the x-api-key header. Replace the values in {{braces}} with fields from your workflow.
Refresh a person
Pass a LinkedIn profile URL as url. Map currentCompany.name, currentCompany.linkedInId, currentTitle, titleSource and profileState into your workflow or spreadsheet. Compare against your saved employer/title and preserve existing values when the result is unavailable.
Find a local business
Map places[0].website, places[0].phone, places[0].address, places[0].totalScore and places[0].reviewsCount. Check the returned name, address and website before accepting a match. This is a business search; the first result is not a guaranteed domain-to-company match.
Keep API keys in your tool’s credential settings. Use the returned JSON fields in the next step of your workflow.
AI agents
Use the MCP server for its supported tools, or the HTTP API for Refresh and other endpoint options. Give your agent llms.txt for usage guidance and the OpenAPI specification for request and response schemas.
Agent payments (x402)
Your agent doesn't need a signup, a card, or a key to start. It can buy its own credits with x402, the open HTTP payment standard. If your agent framework already speaks x402, this works with no extra code from you.
Here's the whole handshake.
- Your agent calls
POST /v1/x402/topup?pack=agentwith no key. - We answer
402 Payment Requiredwith the amount, where to pay, and the USDC contract on Base. - The agent's wallet signs a gasless USDC authorization (EIP-3009) and sends the request again with the signature.
- We verify and settle it on-chain, then hand back a real API key that's already loaded with credits.
From there the key works like any other. The agent calls /v1/search and spends the credits it just bought.
The 402 challenge
Call the top-up endpoint with no key and you get back the payment terms.
After payment
Your x402 client signs the authorization and retries. We settle it and return a key that's ready to use.
A few things worth knowing:
- Payment is USDC on Base, and it's gasless. Your agent signs an authorization, so it doesn't need ETH to pay for gas.
- The agent pack is a $5 first deposit for 2,500 credits. The bigger packs work the same way, just pass a different pack as you scale up.
- This keyless x402 path uses its own credit packs and creates a separate agent key. It does not add USD funds to an existing dashboard wallet. Its returned pack price and credit quantity remain authoritative. Empty results are free.
Ask your AI
Still have questions? Copy this md file with detailed product description to ask your agent about it.
Agents can fetch it directly at crustapi.com/llms.txt.
Stuck on something that isn't here? Email support@crustapi.com and a human will answer.