Is LI Prospect Finder safe?
LIPF is medium risk. When LI Prospect Finder can't parse certain LinkedIn search-result pages locally, it posts the page HTML to li-prospect-finder.com. The posted JSON's html field carries the full document, including rendering data used to extract records.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
LinkedIn search HTML sent to parsing endpoints
When LI Prospect Finder can't parse certain LinkedIn search-result pages locally, it posts the page HTML to li-prospect-finder.com.
The posted JSON's html field carries the full document, including rendering data used to extract records.
You run a LinkedIn company or people search through the extension.
The fallback paths appear when LinkedIn pages use the newer rendering data or when local people parsers return no results.
The extension posts the LinkedIn search-result HTML to its vendor server for parsing.
The request body is JSON with an html field containing the page document.
| Field | Value | Why it matters | |
|---|---|---|---|
LinkedIn page HTML | Illustrative HTML: <html><script>window.__como_rehydration__ = {"data":{"searchDashClustersByAll":{"metadata":{"primaryResultType":"COMPANIES"}}}}</script></html> | This can include the search-result markup and embedded LinkedIn rendering data for the profiles or companies shown on the page. | |
Request field name | html | The server receives the page document under a single html field, which is enough to reconstruct the search results being parsed. |
| Accept | application/json |
| Ext-Version | 3.2.12 |
| Content-Type | application/json |
| Accept | application/json |
| Ext-Version | 3.2.12 |
| Content-Type | application/json |
Fallbacks that send LinkedIn search-result HTML
async function getCompaniesFromDefaultSearch() {
let e = WEB_REQUEST_LI_API_URLS.COMPANIES_SEARCH;
!0 === tab.url?.toLowerCase().includes("schools") && (e = WEB_REQUEST_LI_API_URLS.SCHOOLS_SEARCH);
var a = await getLocalStorageValue(e);
a && a[tab.id] && (searchUrl = a[tab.id], csrfToken) && (a = {
"csrf-token": this.csrfToken,
"x-restli-protocol-version": "2.0.0"
}, 0 < searchUrl.indexOf(WEB_REQUEST_LI_API_URLS.NEW_API) && (a.accept = "application/vnd.linkedin.normalized+json+2.1"), $.ajaxSetup({
headers: a,
global: !1,
type: "GET"
}));
let t = !1,
s = "";
tab.url?.toLowerCase().includes("companies") && (s = await $.get(tab.url) || "", t = s.includes("window.__como_rehydration__")), t ? companies = await apiCompaniesInfoFromHtml({
html: s
}) || [] : (a = await $.get(searchUrl), (companies = liSearchCompaniesParser.handle(a)) && 0 !== companies.length || (companies = liSearchCompaniesParser.getCompanies(a))), renderCompaniesList()
}async getPeopleListV4(e) {
return {
people: (await apiProspectsInfoFromHtml({
html: e
}) || []).map(e => ({
...e,
source: "linkedIn",
searchLink: `https://www.linkedin.com/voyager/api/identity/dash/profiles?q=memberIdentity&memberIdentity=${e.source_id_2}&decorationId=com.linkedin.voyager.dash.deco.identity.profile.FullProfileWithEntities-26`
})),
hasUnadded: !1
}
}async goToNextSearchPage() {
let t = !1;
if (!this.isFinished && !this.isPaused && this.isStarted) {
var s;
if (this.currentCompanies = [], (!0 === this.urlStart?.toLowerCase().includes("results/companies") || !0 === this.urlStart?.toLowerCase().includes("results/schools") || 0 < this.urlCurrent.indexOf(WEB_REQUEST_LI_API_URLS.NEW_API)) && (t = !0), +this.pageCurrent != +this.pageStart) return !(+this.pageCurrent <= +this.pageFinish) || (this.errorInternetCount = 0, this.urlCurrent = this.getCurrentSearchUrl(this.urlStart), 0 < this.urlCurrent.indexOf(WEB_REQUEST_LI_API_URLS.NEW_API) && $.ajaxSetup({
headers: {
accept: "application/vnd.linkedin.normalized+json+2.1"
},
global: !1,
type: "GET"
}), "string" == typeof(s = await $.get(this.urlCurrent)) && s.includes("window.__como_rehydration__") ? this.companies = await apiCompaniesInfoFromHtml({
html: s
}) : this.companies = liSearchCompaniesParser.handle(s), this.companies && 0 !== this.companies.length || (this.list.length ? this.companies = this.list : this.companies = t ? liSearchCompaniesParser.getCompanies(s) : getCompaniesSN(s), this.checkIsPageAbsentError(s, t)), this.isPageAbsentError) ? void await this.finishPageHandler() : (await taskManager.setUnfinishedTask(getDeepCopyOfObject({
...this,
currentCompanies: []
})), void this.sendCompanyBlock());
this.list.length ? this.companies = this.list : this.companies = localStorage.companies ? JSON.parse(localStorage.companies) : [], this.needsSendCompaniesCount = this.companies.length + (this.pageFinish - this.pageStart) * this.companyCountOnPage, await this.sendCompanyBlock()
}
}async goToNextSearchPage() {
if (!this.isFinished && !this.isPaused && this.isStarted)
if (+this.pageCurrent > +this.pageFinish) this.finish && this.finish();
else {
this.errorInternetCount = 0, this.urlCurrent = this.getCurrentSearchUrl(this.urlStart);
var t = this;
if (this.list) i();
else {
let e = this.urlCurrent;
var s = {
"csrf-token": this.csrfToken,
"x-restli-protocol-version": "2.0.0"
},
s = (0 < e.indexOf(WEB_REQUEST_LI_API_URLS.NEW_API) && (s.accept = "application/vnd.linkedin.normalized+json+2.1"), this.requestMethod === REQUEST_METHODS.POST && (e = this.urlCurrent.split("?")[0], s["Content-Type"] = "application/x-www-form-urlencoded", s["x-http-method-override"] = "GET"), {
method: this.requestMethod,
headers: s
});
this.requestMethod === REQUEST_METHODS.POST && (s.body = this.urlCurrent.split("?")[1]);
try {
i(await (await fetch(e, s)).text())
} catch (e) {
0 === e.status ? (t.error = !0, t.errorCode = 0, t.errorOnPageGlobal()) : t.errorOnPage()
}
}
} async function i(e) {
!e && t.list ? (t.people = t.list, t.list = void 0) : (t.people = t.getPeopleList(e), t.people && t.people?.length || t.isSalesNavInt || (t.people = (await (new searchProspectsParser).getPeopleListV4(e))?.people)), t.getTrackingInfo && (t.trackingInfo = t.getTrackingInfo(e)), t.people && 0 < t.people.length ? (e = await t.checkPrevAddedPeople(t.people) || !1, t.needRecheckPrevAdded = e, await t.checkRecentlyUpdatedPeoples(t.people), t.itemsParsed = 0, t.waitAndGetPerson(), await reRenderTask(t)) : (t.itemsParsed = 0, t.waitAndGetPerson(), reRenderTask(t)), await reRenderTask(t)
}
}The API wrapper builds POST requests to the parsing endpoints
let API_HOST = APP_HOST + "/extension/api",
USER_BALANCE = "/user/balance",
PEOPLE_CREATE = "/peoples/create",
PEOPLE_CONTACTS = "/peoples/contacts",
PEOPLE_RECENTLY_UPDATED = "/peoples/recently-updated",
COMPANIES_CREATE = "/companies/create",
LISTS_BY_USER = "/lists/get-by-user-id",
LISTS_BY_PROSPECTS = "/lists/get-by-peoples-ids",
LISTS_BY_COMPANIES = "/lists/get-by-companies-ids",
NEWS_GET = "/news/get-last",
LI_HTML = "/linkedin/collect",
COMPANIES_PARSE = "/companies/parse",
PROSPECTS_PARSE = "/peoples/parse";
function post(e, a) {
return fetch(e, {
method: "POST",
body: JSON.stringify(a),
headers: {
"Content-Language": getUILanguage(),
"Ext-Version": chrome.runtime.getManifest().version,
"Content-Type": "application/json",
Accept: "application/json"
}
})
}async function apiCompaniesInfoFromHtml(e) {
e = await post(API_HOST + COMPANIES_PARSE, e);
return e.ok && (await e.json())?.companies || []
}
async function apiProspectsInfoFromHtml(e) {
e = await post(API_HOST + PROSPECTS_PARSE, e);
return e.ok && (await e.json())?.peoples || []
}- li-prospect-finder.com
LI Prospect Finder vendor host that receives LinkedIn search-result HTML at /extension/api/companies/parse and /extension/api/peoples/parse.