In this digital era, everyone needs leads from their targeted audience and actually, they are buying data from others. What happens if you can scrap data of your selected WhatsApp group user to target and you don't need to install anything for that you can do it just from your web Whatsapp via browser, imagine how useful it is for you.
Script to scrape WhatsApp group members and export them into a CSV file. This WhatsApp member's exporter works in the browser, without installing an extension or using a proxy.
Open WhatsApp web client https://web.whatsapp.com, copy-paste the script into your Chrome console, and open the group members modal. Then scroll to scrape the member.
You may like to read more about : Effortless Facebook Group Member Extraction: Easy Script for Quick Data Collection
What type of data they can scrap
- Phone Number: Member phone number
- Name: Name shown on the modal. When available.
- Description: WhatsApp member description. When available.
- Source: Name of the WhatsApp group
How to run the WhatsApp Users Extractor script
- Open the WhatsApp Web Client on Chrome
- Open Chrome Developer Console
- Copy and Paste the following code into the console. It will add a "Download 0 users" button. Important: Copy/Paste before opening the group member's modal
- Click on "Group info" and "View all" in the members listing. It opens the group members modal.
- Scroll to load new users that will get scraped by the script. The button counter increases with new users scraped.
- Scroll several times between the top and the bottom.
- Once the counter stops increasing, click on the "Download X users" button to download the generated CSV file
- The profiles are kept in a cache until you click the "Reset" button. Thanks to this cache, the extracted profiles are still available if your browser "crashes".
Copy and Paste the Below Command Into the Console
function exportToCsv(e,t){for(var n="",r=0;re.some(e=>t instanceof e);let idbProxyableTypes,cursorAdvanceMethods;function getIdbProxyableTypes(){return idbProxyableTypes=idbProxyableTypes||[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction]}function getCursorAdvanceMethods(){return cursorAdvanceMethods=cursorAdvanceMethods||[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey]}const transactionDoneMap=new WeakMap,transformCache=new WeakMap,reverseTransformCache=new WeakMap;function promisifyRequest(i){var e=new Promise((e,t)=>{const n=()=>{i.removeEventListener("success",r),i.removeEventListener("error",o)},r=()=>{e(wrap(i.result)),n()},o=()=>{t(i.error),n()};i.addEventListener("success",r),i.addEventListener("error",o)});return reverseTransformCache.set(e,i),e}function cacheDonePromiseForTransaction(i){var e;transactionDoneMap.has(i)||(e=new Promise((e,t)=>{const n=()=>{i.removeEventListener("complete",r),i.removeEventListener("error",o),i.removeEventListener("abort",o)},r=()=>{e(),n()},o=()=>{t(i.error||new DOMException("AbortError","AbortError")),n()};i.addEventListener("complete",r),i.addEventListener("error",o),i.addEventListener("abort",o)}),transactionDoneMap.set(i,e))}let idbProxyTraps={get(e,t,n){if(e instanceof IDBTransaction){if("done"===t)return transactionDoneMap.get(e);if("store"===t)return n.objectStoreNames[1]?void 0:n.objectStore(n.objectStoreNames[0])}return wrap(e[t])},set(e,t,n){return e[t]=n,!0},has(e,t){return e instanceof IDBTransaction&&("done"===t||"store"===t)||t in e}};function replaceTraps(e){idbProxyTraps=e(idbProxyTraps)}function wrapFunction(t){return getCursorAdvanceMethods().includes(t)?function(...e){return t.apply(unwrap(this),e),wrap(this.request)}:function(...e){return wrap(t.apply(unwrap(this),e))}}function transformCachableValue(e){return"function"==typeof e?wrapFunction(e):(e instanceof IDBTransaction&&cacheDonePromiseForTransaction(e),instanceOfAny(e,getIdbProxyableTypes())?new Proxy(e,idbProxyTraps):e)}function wrap(e){if(e instanceof IDBRequest)return promisifyRequest(e);if(transformCache.has(e))return transformCache.get(e);var t=transformCachableValue(e);return t!==e&&(transformCache.set(e,t),reverseTransformCache.set(t,e)),t}const unwrap=e=>reverseTransformCache.get(e);function openDB(e,t,{blocked:n,upgrade:r,blocking:o,terminated:i}={}){const a=indexedDB.open(e,t),s=wrap(a);return r&&a.addEventListener("upgradeneeded",e=>{r(wrap(a.result),e.oldVersion,e.newVersion,wrap(a.transaction),e)}),n&&a.addEventListener("blocked",e=>n(e.oldVersion,e.newVersion,e)),s.then(e=>{i&&e.addEventListener("close",()=>i()),o&&e.addEventListener("versionchange",e=>o(e.oldVersion,e.newVersion,e))}).catch(()=>{}),s}const readMethods=["get","getKey","getAll","getAllKeys","count"],writeMethods=["put","add","delete","clear"],cachedMethods=new Map;function getMethod(e,t){if(e instanceof IDBDatabase&&!(t in e)&&"string"==typeof t){if(cachedMethods.get(t))return cachedMethods.get(t);const r=t.replace(/FromIndex$/,""),o=t!==r,i=writeMethods.includes(r);return r in(o?IDBIndex:IDBObjectStore).prototype&&(i||readMethods.includes(r))?(e=async function(e,...t){e=this.transaction(e,i?"readwrite":"readonly");let n=e.store;return o&&(n=n.index(t.shift())),(await Promise.all([n[r](...t),i&&e.done]))[0]},cachedMethods.set(t,e),e):void 0}}replaceTraps(r=>({...r,get:(e,t,n)=>getMethod(e,t)||r.get(e,t,n),has:(e,t)=>!!getMethod(e,t)||r.has(e,t)}));const advanceMethodProps=["continue","continuePrimaryKey","advance"],methodMap={},advanceResults=new WeakMap,ittrProxiedCursorToOriginalProxy=new WeakMap,cursorIteratorTraps={get(e,t){if(!advanceMethodProps.includes(t))return e[t];let n=methodMap[t];return n=n||(methodMap[t]=function(...e){advanceResults.set(this,ittrProxiedCursorToOriginalProxy.get(this)[t](...e))})}};async function*iterate(...e){let t=this;if(t=t instanceof IDBCursor?t:await t.openCursor(...e)){t=t;var n=new Proxy(t,cursorIteratorTraps);for(ittrProxiedCursorToOriginalProxy.set(n,t),reverseTransformCache.set(n,unwrap(t));t;)yield n,t=await(advanceResults.get(n)||t.continue()),advanceResults.delete(n)}}function isIteratorProp(e,t){return t===Symbol.asyncIterator&&instanceOfAny(e,[IDBIndex,IDBObjectStore,IDBCursor])||"iterate"===t&&instanceOfAny(e,[IDBIndex,IDBObjectStore])}replaceTraps(r=>({...r,get(e,t,n){return isIteratorProp(e,t)?iterate:r.get(e,t,n)},has(e,t){return isIteratorProp(e,t)||r.has(e,t)}}));var __awaiter$1=function(e,a,s,c){return new(s=s||Promise)(function(n,t){function r(e){try{i(c.next(e))}catch(e){t(e)}}function o(e){try{i(c.throw(e))}catch(e){t(e)}}function i(e){var t;e.done?n(e.value):((t=e.value)instanceof s?t:new s(function(e){e(t)})).then(r,o)}i((c=c.apply(e,a||[])).next())})},__rest=function(e,t){var n={};for(o in e)Object.prototype.hasOwnProperty.call(e,o)&&t.indexOf(o)<0 constructor="" e.name="" e="" for="" function="" if="" liststorage="" map="" n="" null="" o="" object.getownpropertysymbols="" r="0,o=Object.getOwnPropertySymbols(e);r<o.length;r++)t.indexOf(o[r])<0&&Object.prototype.propertyIsEnumerable.call(e,o[r])&&(n[o[r]]=e[o[r]]);return" this.name="e.name),null!=e&&e.persistent&&(this.persistent=e.persistent),this.initDB().then(()=" this.persistent="!0,this.data=new" typeof="" var="">{}).catch(()=>{this.persistent=!1})}get storageKey(){return"storage-"+this.name}initDB(){return __awaiter$1(this,void 0,void 0,function*(){this.db=yield openDB(this.storageKey,6,{upgrade(e,t,n,r){let o;if(t<5 0="" __awaiter="" a="" addelem="" addelems="" autoincrement:="" bject.assign="" catch="" console.error="" const="" createdat="" data="" date="" dbgetelem="" dbsetelem="" doesnt="" e.createobjectstore="" e.deleteobjectstore="" e.index="" e="" else="" error="" exist="" function="" get="" getelem="" groupid="" i="!1,a){return" id="" if="" keypath:="" let="" n.index="" n.put="" n="[],r=this.db.transaction(" new="" o.createindex="" o.indexnames.contains="" o="[];if(t.forEach(([e,t])=" pk="" r._groupid="s),yield" r.objectstore="" r="" readonly="" readwrite="" return="" s="" store="" t="" this._dbgetelem="" this._dbsetelem="" this.data.get="" this.data.set="" this.db="" this.persistent="" this="" throw="" try="" unique:="" var="" void="" yield="">{-1===o.indexOf(e)&&(o.push(e),n.push(this._dbSetElem(e,t,i,a,r)))}),0{"boolean"==typeof e&&e&&(t+=1)}),t}return 0}return t.forEach(([e,t])=>{this.addElem(e,t)}),t.length})}deleteFromGroupId(r){return __awaiter$1(this,void 0,void 0,function*(){if(this.persistent&&this.db){let e=0;const n=this.db.transaction("data","readwrite");let t=yield n.store.index("_groupId").openCursor(IDBKeyRange.only(r));for(;t;)t.delete(),t=yield t.continue(),e+=1;return e}throw new Error("Not Implemented Error")})}clear(){return __awaiter$1(this,void 0,void 0,function*(){this.persistent&&this.db?yield this.db.clear("data"):this.data.clear()})}getCount(){return __awaiter$1(this,void 0,void 0,function*(){return this.persistent&&this.db?yield this.db.count("data"):this.data.size})}getAll(){return __awaiter$1(this,void 0,void 0,function*(){if(this.persistent&&this.db){const n=new Map,e=yield this.db.getAll("data");return e&&e.forEach(e=>{var t=e["_id"],e=__rest(e,["_id"]);n.set(t,e)}),n}return this.data})}toCsvData(){return __awaiter$1(this,void 0,void 0,function*(){const t=[],e=(t.push(this.headers),yield this.getAll());return e.forEach(e=>{try{t.push(this.itemToRow(e))}catch(e){console.error(e)}}),t})}}const btnStyles=["display: block;","padding: 0px 4px;","cursor: pointer;","text-align: center;"];function createCta(e){const t=document.createElement("div"),n=[...btnStyles];return e&&n.push("flex-grow: 1;"),t.setAttribute("style",n.join("")),t}const spacerStyles=["margin-left: 4px;","margin-right: 4px;","border-left: 1px solid #2e2e2e;"];function createSpacer(){const e=document.createElement("div");return e.innerHTML=" ",e.setAttribute("style",spacerStyles.join("")),e}function createTextSpan(e,t){var n,t=t||{};let r;const o=document.createElement("span");return(r=t.bold?(n=document.createElement("strong"),o.append(n),n):o).textContent=e,t.idAttribute&&r.setAttribute("id",t.idAttribute),o}const canvasStyles=["position: fixed;","top: 0;","left: 0;","z-index: 10000;","width: 100%;","height: 100%;","pointer-events: none;"],innerStyles=["position: absolute;","bottom: 30px;","right: 30px;","width: auto;","pointer-events: auto;"],ctaContainerStyles=["align-items: center;","appearance: none;","background-color: #EEE;","border-radius: 4px;","border-width: 0;","box-shadow: rgba(45, 35, 66, 0.4) 0 2px 4px,rgba(45, 35, 66, 0.3) 0 7px 13px -3px,#D6D6E7 0 -3px 0 inset;","box-sizing: border-box;","color: #36395A;","display: flex;","font-family: monospace;","height: 38px;","justify-content: space-between;","line-height: 1;","list-style: none;","overflow: hidden;","padding-left: 16px;","padding-right: 16px;","position: relative;","text-align: left;","text-decoration: none;","user-select: none;","white-space: nowrap;","font-size: 18px;"];class UIContainer{constructor(){this.ctas=[],this.canva=document.createElement("div"),this.canva.setAttribute("style",canvasStyles.join("")),this.inner=document.createElement("div"),this.inner.setAttribute("style",innerStyles.join("")),this.canva.appendChild(this.inner),this.history=document.createElement("div"),this.inner.appendChild(this.history),this.container=document.createElement("div"),this.container.setAttribute("style",ctaContainerStyles.join("")),this.inner.appendChild(this.container)}makeItDraggable(){let t=0,n=0,r=0,o=0;const i=e=>{r=e.clientX-t,o=e.clientY-n,this.inner.style.right=window.innerWidth-r-this.inner.offsetWidth+"px",this.inner.style.bottom=window.innerHeight-o-this.inner.offsetHeight+"px"};this.inner.addEventListener("mousedown",e=>{e.preventDefault(),t=e.clientX-this.inner.offsetLeft,n=e.clientY-this.inner.offsetTop,window.addEventListener("mousemove",i,!1)},!1),window.addEventListener("mouseup",()=>{window.removeEventListener("mousemove",i,!1)},!1);const e=document.createElement("div");e.style.cursor="move",e.innerHTML='',this.addCta(createSpacer()),this.addCta(e)}render(){document.body.appendChild(this.canva)}addCta(e,t){void 0===t?this.ctas.push(e):this.ctas.splice(t,0,e),this.container.innerHTML="",this.ctas.forEach(e=>{this.container.appendChild(e)})}}var LogCategory,__awaiter=function(e,a,s,c){return new(s=s||Promise)(function(n,t){function r(e){try{i(c.next(e))}catch(e){t(e)}}function o(e){try{i(c.throw(e))}catch(e){t(e)}}function i(e){var t;e.done?n(e.value):((t=e.value)instanceof s?t:new s(function(e){e(t)})).then(r,o)}i((c=c.apply(e,a||[])).next())})};!function(e){e.ADD="add",e.LOG="log"}(LogCategory=LogCategory||{});const historyPanelStyles=["text-align: right;","background: #f5f5fa;","padding: 8px;","margin-bottom: 8px;","border-radius: 8px;","font-family: monospace;","font-size: 16px;","box-shadow: rgba(42, 35, 66, 0.2) 0 2px 2px,rgba(45, 35, 66, 0.2) 0 7px 13px -4px;","color: #2f2f2f;"],historyUlStyles=["list-style: none;","margin: 0;"],historyLiStyles=["line-height: 30px;","display: flex;","align-items: center;","justify-content: right;"],deleteIconStyles=["display: flex;","align-items: center;","padding: 4px 12px;","cursor: pointer;"],deleteIconSvg='';class HistoryTracker{constructor({onDelete:e,divContainer:t,maxLogs:n}){this.maxLogs=5,this.logs=[],this.panelRef=null,this.counter=0,this.onDelete=e,this.container=t,n&&(this.maxLogs=n)}renderPanel(){const e=document.createElement("div");return e.setAttribute("style",historyPanelStyles.join("")),e}renderLogs(){if(this.panelRef&&this.panelRef.remove(),0!==this.logs.length){const o=document.createElement("ul"),e=(o.setAttribute("style",historyUlStyles.join("")),this.logs.forEach(t=>{const e=document.createElement("li");e.setAttribute("style",historyLiStyles.join(""));let n;if(n=t.category===LogCategory.ADD?`#${t.index} ${t.label} (${t.numberItems})`:`#${t.index} ${t.label}`,e.innerHTML=n,t.category===LogCategory.ADD&&t.cancellable){const r=document.createElement("div");r.setAttribute("style",deleteIconStyles.join("")),r.innerHTML=deleteIconSvg,r.addEventListener("click",()=>__awaiter(this,void 0,void 0,function*(){yield this.onDelete(t.groupId);var e=this.logs.findIndex(e=>e.index===t.index);-1!==e&&(this.logs.splice(e,1),this.renderLogs())})),e.append(r)}o.prepend(e)}),this.renderPanel());e.appendChild(o),this.panelRef=e,this.container.appendChild(e)}}addHistoryLog(e){this.counter+=1;let t;if(e.category===LogCategory.ADD)t={index:this.counter,label:e.label,groupId:e.groupId,numberItems:e.numberItems,cancellable:e.cancellable,createdAt:new Date,category:LogCategory.ADD};else{if(e.category!==LogCategory.LOG)return void console.error("Missing category");t={index:this.counter,label:e.label,createdAt:new Date,category:LogCategory.LOG}}this.logs.unshift(t),this.logs.length>this.maxLogs&&this.logs.splice(this.maxLogs),this.renderLogs()}cleanLogs(){this.logs=[],this.counter=0,this.renderLogs()}}function cleanName(e){const t=e.trim();return t.replace("~ ","")}function cleanDescription(e){const t=e.trim();return t.match(/Loading About/i)||t.match(/I am using WhatsApp/i)||t.match(/Available/i)?null:t}class WhatsAppStorage extends ListStorage{get headers(){return["Phone Number","Name","Description","Source"]}itemToRow(e){return[e.phoneNumber||"",e.name||"",e.description||"",e.source||""]}}const memberListStore=new WhatsAppStorage({name:"whatsapp-scraper"}),counterId="scraper-number-tracker",exportName="whatsAppExport";let logsTracker;async function updateConter(){const e=document.getElementById(counterId);if(e){const t=await memberListStore.getCount();e.textContent=t.toString()}}const uiWidget=new UIContainer;function buildCTABtns(){logsTracker=new HistoryTracker({onDelete:async e=>{console.log("Delete "+e),await memberListStore.deleteFromGroupId(e),await updateConter()},divContainer:uiWidget.history,maxLogs:4});const e=createCta(),t=(e.appendChild(createTextSpan("Download ")),e.appendChild(createTextSpan("0",{bold:!0,idAttribute:counterId})),e.appendChild(createTextSpan(" users")),e.addEventListener("click",async function(){var e=(new Date).toISOString(),t=await memberListStore.toCsvData();try{exportToCsv(exportName+`-${e}.csv`,t)}catch(e){console.error("Error while generating export"),console.log(e.stack)}}),uiWidget.addCta(e),uiWidget.addCta(createSpacer()),createCta());t.appendChild(createTextSpan("Reset")),t.addEventListener("click",async function(){await memberListStore.clear(),logsTracker.cleanLogs(),await updateConter()}),uiWidget.addCta(t),uiWidget.makeItDraggable(),uiWidget.render(),window.setTimeout(()=>{updateConter()},1e3)}let modalObserver;function listenModalChanges(){var e=document.querySelectorAll("header span[style*='height']:not(.copyable-text)");let s;1==e.length&&(s=e[0].textContent);const t=document.querySelectorAll('[data-animate-modal-body="true"]')[0];e=t.querySelectorAll("div[style*='height']")[1];(modalObserver=new MutationObserver(e=>{for(const t of e)if("childList"===t.type){if(0{let e="",t="",n="";var r=a.querySelectorAll("span[title]:not(.copyable-text)");if(0{const t=e;0{listenModalChanges(),logsTracker.addHistoryLog({label:"Modal found - Scroll to scrape",category:LogCategory.LOG})},10)}),0{const t=e;0 5>0>
Hackersking
- How to remove the "Download" button?
Just reload your WhatsApp page. Any javascript code added in Chrome Developer Console will be removed.
- How many users can be extracted?
The script stores the extracted users in a database. There is no limit on the number of users you can extract.
- Can I extract users from different groups?
Yes. The exported CSV contains a "Source" attribute. You can extract users from different sources and use the "Source" attribute to segment your data later on.
- What is the "Reset" button?
The users are stored in a cache in your browser. The cache is kept if your browser restarts the page (intentionally or after a crash). When you copy/paste the script, it loads the previous profiles from the cache. The "Reset" button clears the cache.
- Is it free?
The script is free and open-source. You can also clean and parse the data with a free account on Datablist.