From 84ee539139731fc88244efed8f0d31cd0981a075 Mon Sep 17 00:00:00 2001
From: Quan Dang <18520339@gm.uit.edu.vn>
Date: Tue, 30 Jan 2024 04:19:29 +0700
Subject: [PATCH] Update IP hiding techniques knowledge in README.md
---
.gitignore | 5 +
.../README.md | 67 ---
.../.gitignore | 1 -
.../LICENSE | 21 -
.../README.md | 46 ---
.../README.md | 8 -
README.md | 387 +++++++++++++++++-
assets/nodemaven-test.jpg | Bin 0 -> 61337 bytes
assets/token-business.png | Bin 0 -> 98475 bytes
.../example.xlsx => devtools-data.xlsx | Bin
graph-api/README.md | 59 +++
.../crawler.py | 25 +-
.../data}/KTXDHQGConfessions.jsonl | 0
.../data}/devoiminhdidauthe.jsonl | 0
stealth-csr-puppeteer/README.md | 1 +
stealth-csr-puppeteer/index.js | 97 +++++
stealth-csr-puppeteer/package.json | 10 +
stealth-csr-puppeteer/test.js | 53 +++
stealth-csr-puppeteer/utils.js | 48 +++
.../README.md | 66 ++-
.../browser.py | 0
.../crawler.py | 0
.../data/KTXDHQGConfessions.json | 0
.../data/KTXDHQGConfessions.jsonl | 0
.../data/data.json | 0
.../img/filter.png | Bin
.../img/proxy.png | Bin
.../img/rate_limit_exceeded.png | Bin
.../img/result.png | Bin
.../page.py | 0
.../requirements.txt | 0
.../tor/linux/PluggableTransports/obfs4proxy | Bin
.../tor/linux/libcrypto.so.1.1 | Bin
.../tor/linux/libevent-2.1.so.7 | Bin
.../tor/linux/libssl.so.1.1 | Bin
.../tor/linux/libstdc++/libstdc++.so.6 | Bin
.../tor/linux/tor | Bin
.../tor/mac/PluggableTransports/obfs4proxy | Bin
.../tor/mac/libevent-2.1.7.dylib | Bin
.../tor/mac/tor.real | Bin
.../PluggableTransports/obfs4proxy.exe | Bin
.../tor/windows/libcrypto-1_1-x64.dll | Bin
.../tor/windows/libevent-2-1-7.dll | Bin
.../tor/windows/libevent_core-2-1-7.dll | Bin
.../tor/windows/libevent_extra-2-1-7.dll | Bin
.../tor/windows/libgcc_s_seh-1.dll | Bin
.../tor/windows/libssl-1_1-x64.dll | Bin
.../tor/windows/libssp-0.dll | Bin
.../tor/windows/libwinpthread-1.dll | Bin
.../tor/windows/tor.exe | Bin
.../tor/windows/zlib1.dll | Bin
stealth-ssr-puppeteer/README.md | 1 +
stealth-ssr-scrapy/README.md | 1 +
stealth-ssr-scrapy/fbscraper/__init__.py | 0
stealth-ssr-scrapy/fbscraper/items.py | 12 +
stealth-ssr-scrapy/fbscraper/middlewares.py | 103 +++++
stealth-ssr-scrapy/fbscraper/pipelines.py | 13 +
stealth-ssr-scrapy/fbscraper/settings.py | 93 +++++
.../fbscraper/spiders/__init__.py | 4 +
stealth-ssr-scrapy/scrapy.cfg | 11 +
60 files changed, 922 insertions(+), 210 deletions(-)
create mode 100644 .gitignore
delete mode 100644 1 - Personal account Access Token with Graph API/README.md
delete mode 100644 2 - Automation tools with IP hiding techniques/.gitignore
delete mode 100644 2 - Automation tools with IP hiding techniques/LICENSE
delete mode 100644 3 - Run JS code directly at the DevTools Console/README.md
delete mode 100644 4 - Mbasic Facebook + IP hiding techniques/README.md
create mode 100644 assets/nodemaven-test.jpg
create mode 100644 assets/token-business.png
rename 3 - Run JS code directly at the DevTools Console/example.xlsx => devtools-data.xlsx (100%)
create mode 100644 graph-api/README.md
rename {1 - Personal account Access Token with Graph API => graph-api}/crawler.py (95%)
rename {1 - Personal account Access Token with Graph API => graph-api/data}/KTXDHQGConfessions.jsonl (100%)
rename {1 - Personal account Access Token with Graph API => graph-api/data}/devoiminhdidauthe.jsonl (100%)
create mode 100644 stealth-csr-puppeteer/README.md
create mode 100644 stealth-csr-puppeteer/index.js
create mode 100644 stealth-csr-puppeteer/package.json
create mode 100644 stealth-csr-puppeteer/test.js
create mode 100644 stealth-csr-puppeteer/utils.js
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/README.md (62%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/browser.py (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/crawler.py (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/data/KTXDHQGConfessions.json (100%)
rename 2 - Automation tools with IP hiding techniques/data/KTXDHQGConfessions-inline.json => stealth-csr-selenium/data/KTXDHQGConfessions.jsonl (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/data/data.json (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/img/filter.png (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/img/proxy.png (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/img/rate_limit_exceeded.png (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/img/result.png (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/page.py (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/requirements.txt (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/linux/PluggableTransports/obfs4proxy (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/linux/libcrypto.so.1.1 (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/linux/libevent-2.1.so.7 (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/linux/libssl.so.1.1 (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/linux/libstdc++/libstdc++.so.6 (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/linux/tor (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/mac/PluggableTransports/obfs4proxy (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/mac/libevent-2.1.7.dylib (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/mac/tor.real (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/windows/PluggableTransports/obfs4proxy.exe (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/windows/libcrypto-1_1-x64.dll (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/windows/libevent-2-1-7.dll (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/windows/libevent_core-2-1-7.dll (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/windows/libevent_extra-2-1-7.dll (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/windows/libgcc_s_seh-1.dll (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/windows/libssl-1_1-x64.dll (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/windows/libssp-0.dll (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/windows/libwinpthread-1.dll (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/windows/tor.exe (100%)
rename {2 - Automation tools with IP hiding techniques => stealth-csr-selenium}/tor/windows/zlib1.dll (100%)
create mode 100644 stealth-ssr-puppeteer/README.md
create mode 100644 stealth-ssr-scrapy/README.md
create mode 100644 stealth-ssr-scrapy/fbscraper/__init__.py
create mode 100644 stealth-ssr-scrapy/fbscraper/items.py
create mode 100644 stealth-ssr-scrapy/fbscraper/middlewares.py
create mode 100644 stealth-ssr-scrapy/fbscraper/pipelines.py
create mode 100644 stealth-ssr-scrapy/fbscraper/settings.py
create mode 100644 stealth-ssr-scrapy/fbscraper/spiders/__init__.py
create mode 100644 stealth-ssr-scrapy/scrapy.cfg
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f6a5b80
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+__pycache__
+node_modules/
+tmp/
+.env
+package-lock.json
\ No newline at end of file
diff --git a/1 - Personal account Access Token with Graph API/README.md b/1 - Personal account Access Token with Graph API/README.md
deleted file mode 100644
index 0b21c91..0000000
--- a/1 - Personal account Access Token with Graph API/README.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Personal account Access Token + Graph API
-
-Use your own Token with **almost full permission** for fetching data. This is the **MOST EFFECTIVE** method.
-
-> The knowledge and the way to get **Access Token** below is translated from these 2 Vietnamese blogs:
->
-> - https://ahachat.com/help/blog/cach-lay-token-facebook
-> - https://alotoi.com/get-token-full-quyen
-
-## Knowledge
-
-### I. What is Facebook Token?
-
-The Facebook token is a randomly generated code that contains the data associated with the Facebook account. Facebook Token, also known as **Access Token** will contain the permissions to perform an action on the library (API) provided by Facebook. Each Facebook account will have different **Access Tokens**. There may be 1 or more Tokens on the same Facebook account.
-
-There are many ways to reach a destination, but for some reason we will have to choose only one, usually the shortest, fastest path. The **Access Token**is a shortcut to that destination. Understand simply Facebook Token is like that.
-
-### II. What are Facebook tokens used for?
-
-Facebook Token is now quite popular in the field of Facebook Marketing, depending on the limit of the permissions of each token. Some popular applications of Facebook Token:
-
-- Increase Facebook likes and subs.
-- Automatically post on Facebook.
-- Automatically comment, share articles.
-- Automatically interact in groups, pages.
-- ...
-
-It is used for many different purposes, but the main goal is still to automate all manual operations. With Facebook Token, you can use some features that Facebook has not yet supported or supported in some countries. For example, you won't be able to do the feature of enabling the Facebook Avatar protection shield without using tokens (or Extensions) if in some other countries (India, Germany, ...), then you will find the option to enable shields right on the Facebook account itself.
-
-### III. Facebook Token types
-
-There are 2 types of Facebook Tokens: **Token by App** and **Token by Personal Account**. The Facebook Token by App is the safest one, as it will have a limited lifetime and only has some basic permissions to manipulate on pages and groups. So our main focus will on the Facebook **Token by Personal Account**.
-
-### IV. Facebook Token by Personal Account
-
-This is a **full permissions** token represented by a string of characters starting with `EAA...`, the purpose of this token is to represent your Facebook account to perform actions you can do on Facebook, such as sending messages, like pages, and posts to groups through `API`. Compared to **Token by App**, this token has a longer lifetime and more authority. To make it easier to understand what **Token by App** can do, **Token by Personal Account** can also, but not vice versa.
-
-An example of using this token is that you want to post simultaneously to many groups and many pages; to do this, you cannot log in to each page or group to post because it will be very time-consuming. Just fill in a list of group and page ids, then call an `API` to post them all. Or as you often see on the market, there are tools to increase fake likes, and fake comments are also using this trick.
-
-Note that using Facebook token can save you time, but you should not disclose this token to others because they can abuse it for bad purposes, by:
-
-- Do not download extensions to get tokens or login your phone number and password to websites that support getting tokens because your information will be exposed.
-- And if you suspect your token has been exposed, immediately change your Facebook password and delete the extensions installed in the browser. Or if you are more careful you can turn on **two-factor authentication** (2FA).
-
-👉 To ensure the safety of using Facebook tokens for personal purposes and save time, as mentioned above, you should use the method of getting tokens directly on Facebook by following the steps below.
-
-## Get full permissions Access Token
-
-In the past, getting Facebook tokens were very simple. Now many Facebook services are developing. Getting Facebook tokens is becoming more and more difficult. Facebook also restricts Full rights tokens to avoid Spam and excessive abuse of user behaviors. Or you can get Token, but it will be limited by basic permissions that we do not use, that is nothing compared to sometimes having an account locked (identity verification).
-
-Currently, this is the way to use the most. However, it may require you to authenticate with 2FA (via app or SMS Code). With these simple steps, you can get **almost full permission** token.
-
-- Go to https://business.facebook.com/content_management.
-- Press `Ctrl + U`, then `Ctrl + F` to find the code that contains `EAAG`. Copy the highlighted text, that's the Token you need to get.
-
- ![](https://alotoi.com/wp-content/uploads/2020/08/token-business.png)
-
-- You can go to this [facebook link](https://developers.facebook.com/tools/debug/accesstoken) to check the permissions of the above token.
- ![](https://lh4.googleusercontent.com/0S64t2sjFXjkX8HUjo2GeEW8hyKL88G4lMXkpNF7RgtFCRm0oVPRT--vnoM1rkMyhrRvvHufW9J0ZeP8tPxfo4j5vYityQFM0m06NTI2hq4zk1JMp59W9voHXHYtOjE7zqDGMlhh)
-
-**Note**: I only share how to get **Access Token** from Facebook itself. Revealing tokens can seriously affect your Facebook account. Please refrain from getting tokens from unknown sources!
-
-## Implement data extraction with Graph API
-
-The source of this method is reused from [FBMediaDownloader](https://github.com/HoangTran0410/FBMediaDownloader) with a few more features added
-
-Updating...
diff --git a/2 - Automation tools with IP hiding techniques/.gitignore b/2 - Automation tools with IP hiding techniques/.gitignore
deleted file mode 100644
index ed8ebf5..0000000
--- a/2 - Automation tools with IP hiding techniques/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-__pycache__
\ No newline at end of file
diff --git a/2 - Automation tools with IP hiding techniques/LICENSE b/2 - Automation tools with IP hiding techniques/LICENSE
deleted file mode 100644
index 35c9ca1..0000000
--- a/2 - Automation tools with IP hiding techniques/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2021 Quan Dang
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/3 - Run JS code directly at the DevTools Console/README.md b/3 - Run JS code directly at the DevTools Console/README.md
deleted file mode 100644
index 88282c2..0000000
--- a/3 - Run JS code directly at the DevTools Console/README.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# Run JS code directly at the DevTools Console
-
-Simply to say, this method is just another automation one, the same as the [2nd method](#2) but without using any IP hiding techniques. You just directly write & run JS code in the [DevTools Console](https://developer.chrome.com/docs/devtools/open) of your browser, so it's quite convenient, not required to setup anything.
-
-- You can take a look at this [extremely useful project](https://github.com/jayremnt/facebook-scripts-dom-manipulation) which includes many automation scripts (not just about data extraction) with no Access Token needed for Facebook users by directly manipulating the DOM.
-
-- Here's my example script to collect comments on **a Facebook page when not sign-in**:
-
-```js
-// Go to the page you want to collect, wait until it finishes loading.
-// Open the DevTools Console on the Browser and run the following code
-let csvContents = [['UserId', 'Name', 'Comment']];
-let cmtsSelector = '.userContentWrapper .commentable_item';
-
-// 1. Click see more comments
-// If you want more, just wait until the loading finishes and run this again
-moreCmts = document.querySelectorAll(cmtsSelector + ' ._4sxc._42ft');
-moreCmts.forEach(btnMore => btnMore.click());
-
-// 2. Collect all comments
-comments = document.querySelectorAll(cmtsSelector + ' ._72vr');
-comments.forEach(cmt => {
- let info = cmt.querySelector('._6qw4');
- let userId = info.getAttribute('href')?.substring(1);
- let content = cmt.querySelector('._3l3x>span')?.innerText;
- csvContents.push([userId, info.innerText, content]);
-});
-csvContents.map(cmt => cmt.join('\t')).join('\n');
-```
-
-
-
-
- Example result for the script above
-
-
-
-| UserId | Name | Comment |
-| -------------- | -------------- | ---------------------------------- |
-| freedomabcxyz | Freedom | Sau khi dùng |
-| baodendepzai123 | Bảo Huy Nguyễn | nhưng mà thua |
-| tukieu.2001 | Tú Kiều | đang xem hài ai rãnh xem quãng cáo |
-| ABCDE2k4 | Maa Vănn Kenn | Lê Minh Nhất |
-| buikhanhtoanpro | Bùi Khánh Toàn | Haha |
-
-
\ No newline at end of file
diff --git a/4 - Mbasic Facebook + IP hiding techniques/README.md b/4 - Mbasic Facebook + IP hiding techniques/README.md
deleted file mode 100644
index 4a338d5..0000000
--- a/4 - Mbasic Facebook + IP hiding techniques/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# Mbasic Facebook + IP hiding techniques
-
-There is also another way quite similar to the [2nd method](#2) is to use the [Mbasic Facebook](https://mbasic.facebook.com):
-- This version of Facebook is made for mobile browsers on slow internet connections. You can access it without a modern smartphone.
-- With modern devices, it will improves the page loading time & the contents will be rendered with raw HTML, not JS ➔ You can leverage the power of many web scraping tools ([scrapy](https://scrapy.org), [bs4](https://pypi.org/project/beautifulsoup4), ...) not just automation tools like the [2nd method](#2) and it will become even more powerful when used with [IP hiding techniques](https://github.com/18520339/facebook-data-extraction/tree/master/2%20-%20Automation%20tools%20with%20IP%20hiding%20techniques#ii-ip-hiding-techniques).
-- You can get each part of the contents through different URLs, not only through the page scrolling like the [2nd method](#2) ➔ You can do something like using proxy for each request or [AutoThrottle](https://doc.scrapy.org/en/latest/topics/autothrottle.html) (a built-in [scrapy](https://scrapy.org) extension), ...
-
-**Note**: I haven't tried the extraction with this method yet, so I won't go into details about it.
\ No newline at end of file
diff --git a/README.md b/README.md
index ef12d26..dc1671c 100644
--- a/README.md
+++ b/README.md
@@ -1,29 +1,382 @@
-# Summary of Facebook data extraction methods
+# Summary of Facebook data extraction approaches
-### I. General Comparison
+> I'm editing everything to match the latest big changes
-| Method | Sign-in required | Risk when sign-in | Risk when not sign-in | Difficulty | Speed |
-| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------: | :--------------------------------------------------------------------------------------------------------: | :---------------------: | :--------: | :-------------: |
-| 1️⃣ [Personal account Access Token + Graph API](https://github.com/18520339/facebook-data-extraction/tree/master/1%20-%20Personal%20account%20Access%20Token%20with%20Graph%20API) | ✅ | Access Token leaked, [Rate Limits](https://developers.facebook.com/docs/graph-api/overview/rate-limiting/) | Not working | Easy | Fast |
-| 2️⃣ [Automation tools + IP hiding techniques](https://github.com/18520339/facebook-data-extraction/tree/master/2%20-%20Automation%20tools%20with%20IP%20hiding%20techniques) | Depend **(\*)** | Checkpoint but less _loading more_ failure | Safest | Hard | Slow **(\*\*)** |
-| 3️⃣ [Run JS code directly at the DevTools Console](https://github.com/18520339/facebook-data-extraction/tree/master/3%20-%20Run%20JS%20code%20directly%20at%20the%20DevTools%20Console) | Depend **(\*)** | Checkpoint but less _loading more_ failure | Can be banned if abused | Medium | Slow **(\*\*)** |
-| 4️⃣ [Mbasic Facebook + IP hiding techniques](https://github.com/18520339/facebook-data-extraction/tree/master/4%20-%20Mbasic%20Facebook%20+%20IP%20hiding%20techniques) | Depend **(\*)** | - | - | Hard | - |
+## Overview
-**(\*)** Depend on the tasks that you need to sign in to perform. Example: Tasks that need to access private groups or private posts, ...
+
-**(\*\*)** Depend on how much data you want to extract, the more the number, the more times for scrolling down to load the contents.
+### I. My general conclusion after many tries with different approaches
-### II. My general conclusion after many tries with different methods
+When run at **not sign-in** state, Facebook usually redirects to the login page or prevent you from loading more comments/replies.
-- When run at **not sign-in** state, Facebook usually redirects to the login page or prevent you from loading more comments / replies.
-- No matter which method you use, any fast or irregular activity continuously in **sign-in** state for a long time can be likely to get blocked at any time.
-- If you want to use at **sign-in** state, for safety, I recommend create a **fake account** (you can use a [Temporary Email Address](https://temp-mail.org/en/) to create one) and use it for the extraction.
-- With the **sign-in** state, there's also another technique to limit the Checkpoint is to sign in with different **Cookies**.
+**(*)** For safety when testing with **sign-in** state, I recommend create a **fake account** (you can use a [Temporary Email Address](https://temp-mail.org/en/) to create one) and use it for the extraction, because:
+- No matter which approach you use, any fast or irregular activity continuously in **sign-in** state for a long time can be likely to get blocked at any time.
-### III. DISCLAIMER
+- Authenticating via services with lack of encryption such as proxies using **HTTP** protocol can have potential security risks, especially if sensitive data is being transmitted:
+ - Therefore, if you are experimenting with your own account, it's advisable to use **HTTPS** proxies or other more secure methods like `VPNs`.
+ - I won't implement these types of risky authentication into the sign-in process for approaches in this repo, but you can do it yourself if you want.
+
+### II. DISCLAIMER
All information provided in this repo and related articles are for educational purposes only. So use at your own risk, I will not guarantee & not be responsible for any situations including:
- Whether your Facebook account may get Checkpoint due to repeatedly or rapid actions.
- Problems that may occur or for any abuse of the information or the code provided.
-- Problems about your privacy while using [IP hiding techniques](https://github.com/18520339/facebook-data-extraction/tree/master/2%20-%20Automation%20tools%20with%20IP%20hiding%20techniques#ii-ip-hiding-techniques) or any malicious scripts.
+- Problems about your privacy while using [IP hiding techniques](#i-ip-hiding-techniques) or any malicious scripts.
+
+## APPROACH 1. Graph API with Full-permission Token
+
+👉 Check out my implementation for this approach with [Python](./graph-api/).
+
+You will query [Facebook Graph API](https://developers.facebook.com/docs/graph-api) using your own Token with **full permission** for fetching data. This is the **MOST EFFECTIVE** approach.
+
+> The knowledge and the way to get **Access Token** below are translated from these 2 Vietnamese blogs:
+>
+> - https://ahachat.com/help/blog/cach-lay-token-facebook
+> - https://alotoi.com/get-token-full-quyen
+
+### I. What is Facebook Token?
+
+A Facebook **Access Token** is a randomly generated code that contains data linked to a Facebook account. It contains the permissions to perform an action on the library (API) provided by Facebook. Each Facebook account will have different **Access Tokens**, and there can be ≥ 1 Tokens on the same account.
+
+Depending on the limitations of each Token's permissions, which are generated for use with corresponding features, either many or few, they can be used for various purposes, but the main goal is to automate all manual operations. Some common applications include:
+
+- Increasing likes, subscriptions on Facebook.
+- Automatically posting on Facebook.
+- Automatically commenting and sharing posts.
+- Automatically interacting in groups and Pages.
+- ...
+
+There are 2 types of Facebook Tokens: **App-based Token** and **Personal Account-based Token**. The Facebook **Token by App** is the safest one, as it will have a limited lifetime and only has some basic permissions to interact with `Pages` and `Groups`. Our main focus will on the Facebook **Personal Account-based Token**.
+
+### II. Personal Account-based Access Token
+
+This is a **full permissions** Token represented by a string of characters starting with `EAA...`. The purpose of this Token is to act on behalf of your Facebook account to perform actions you can do on Facebook, such as sending messages, liking pages, and posting in groups through `API`.
+
+Compared to an **App-based Token**, this type of Token has a longer lifespan and more permissions. Simply put, whatever an **App-based Token** can do, a **Personal Account-based Token** can do as well, but not vice versa.
+
+An example of using this Facebook Token is when you want to simultaneously post to many `Groups` and `Pages`. To do this, you cannot simply log into each `Group` or `Page` to post, which is very time-consuming. Instead, you just need to fill in a list of `Group` and `Page` IDs, and then call an `API` to post to all in this list. Or, as you can often see on the Internet, there are tools to increase fake likes and comments also using this technique.
+
+Note that using Facebook Token can save you time, but you should not reveal this Token to others as they can misuse it for malicious purposes:
+
+- Do not download extensions to get Tokens or login with your phone number and password on websites that support Token retrieval, as your information will be compromised.
+- And if you suspect your Token has been compromised, immediately change your Facebook password and delete the extensions installed in the browser.
+- If you wanna be more careful, you can turn on **two-factor authentication** (2FA).
+
+👉 To ensure safety when using the Facebook Token for personal purposes and saving time as mentioned above, you should obtain the Token directly from Facebook following the steps below.
+
+### III. Get Access Token with full permissions
+
+Before, obtaining Facebook Tokens was very simple, but now many Facebook services are developing and getting Facebook Tokens has become more difficult. Facebook also limits Full permission Tokens to prevent Spam and excessive abuse regarding user behavior.
+
+It's possible to obtain a Token, but it might be limited by basic permissions that we do not use. This is not a big issue compared to sometimes having accounts locked (identity verification) on Facebook.
+
+Currently, this is the most used method, but it may require you to authenticate with 2FA (via app or SMS Code). With these following steps, you can get an **almost full permission** Token:
+
+- Go to https://business.facebook.com/business_locations.
+- Press `Ctrl + U`, then `Ctrl + F` to find the code that contains `EAAG`. Copy the highlighted text, that's the Token you want to obtain.
+
+ ![](./assets/token-business.png)
+
+- You can go to this [facebook link](https://developers.facebook.com/tools/debug/accesstoken) to check the permissions of the above Token.
+ ![](https://lh4.googleusercontent.com/0S64t2sjFXjkX8HUjo2GeEW8hyKL88G4lMXkpNF7RgtFCRm0oVPRT--vnoM1rkMyhrRvvHufW9J0ZeP8tPxfo4j5vYityQFM0m06NTI2hq4zk1JMp59W9voHXHYtOjE7zqDGMlhh)
+
+**Note**: I only share how to get **Access Token** from Facebook itself. Revealing Tokens can seriously affect your Facebook account. Please don't get Tokens from unknown sources!
+
+
+## APPROACH 2. SSR - Server-side Rendering
+
+👉 Check out my implementation using 2 [scraping tools](#scraping-tools) for this approach: [Scrapy](./stealth-ssr-scrapy/) (Implementing) and [Puppeteer](./stealth-ssr-puppeteer/) (Implementing).
+
+### I. What is Server-side Rendering?
+
+This is a popular technique for rendering a normally client-side only single-page application (`SPA`) on the **Server** and then sending a fully rendered page to the client. The client's `JavaScript` bundle can then take over and the `SPA` can operate as normal:
+
+```mermaid
+%%{init: {'theme': 'default', 'themeVariables': { 'primaryColor': '#333', 'lineColor': '#666', 'textColor': '#333', }}}%%
+sequenceDiagram
+ participant U as 🌐 User's Browser
+ participant S as 🔧 Server
+ participant SS as 📜 Server-side Scripts
+ participant D as 📚 Database
+ participant B as 🖥️ Browser Engine
+ participant H as 💧 Hydration (SPA)
+
+ rect rgb(235, 248, 255)
+ U->>S: 1. Request 🌐 (URL/Link)
+ Note right of S: Server processes the request
+ S->>SS: 2. Processing 🔄 (PHP, Node.js, Python, Ruby, Java)
+ SS->>D: Execute Business Logic & Query DB
+ D-->>SS: Return Data
+ SS-->>S: 3. Rendering 📄 (Generate HTML)
+ S-->>U: 4. Response 📤 (HTML Page)
+ end
+
+ rect rgb(255, 243, 235)
+ U->>B: 5. Display 🖥️
+ Note right of B: Browser parses HTML, CSS, JS
+ B-->>U: Page Displayed to User
+ end
+
+ alt 6. Hydration (if SPA)
+ rect rgb(235, 255, 235)
+ U->>H: Hydration 💧
+ Note right of H: Attach event listeners\nMake page interactive
+ H-->>U: Page now reactive
+ end
+ end
+```
+
+1. The **user's browser** requests a page.
+2. The **Server** receives and processes request. This involves running necessary **Server-side scripts**, which can be written in languages like *PHP*, *Node.js*, *Python*, ...
+3. These **Server-side scripts** dynamically generate the `HTML` content of the page. This may include executing business logic or querying a database.
+4. The **Server** responds by sending the **fully-rendered HTML** page back to **user's browser**. This response also includes `CSS` and the `JS`, which will be process once the `HTML` is loaded.
+5. The **user's browser** receives the `HTML` response and renders the page. The browser's rendering engine parses the `HTML`, `CSS`, and execute `JS` to display the page.
+6. (Optional) If the application is a `SPA` using a framework like *React*, *Vue*, or *Angular*, an additional process called **Hydration** may occur to attach event listeners to the existing **Server-rendered HTML**:
+ - This is where the client-side `JS` takes over and `binds` event handlers to the **Server-rendered HTML**, effectively turning a static page into a dynamic one.
+ - This allows the application to handle user interactions, manage `state`, and potentially update the `DOM` without the need to render a new page from scratch or return to the **Server** for every action.
+
+| Pros | Cons |
+| --------------------------- | --------------------------- |
+| - Improved initial load time as users see a **fully-rendered page** sooner, which is important for experience, particularly on slow connections | - More **Server** resources are used to generate the **fully-rendered HTML**. |
+| - Improved SEO as search engine crawlers can see the **fully-rendered page**. | - Complex to implement as compared to [CSR](#approach-3-csr---client-side-rendering), especially for dynamic sites where content changes frequently. |
+
+### II. [Mbasic Facebook](https://mbasic.facebook.com) - A Facebook SSR version
+
+This Facebook version is made for mobile browsers on slow internet connection by using [SSR](#i-what-is-server-side-rendering) to focus on delivering content in raw `HTML` format. You can access it without a modern smartphones. With modern devices, it will improves the page loading time & the contents will be mainly rendered using raw `HTML` rather than relying heavily on `JS`:
+
+https://github.com/18520339/facebook-data-extraction/assets/50880271/ae2635ff-3f2a-4b84-a5b3-c126102a0118
+
+- You can leverage the power of many web scraping frameworks like [scrapy](https://scrapy.org) not just automation tools like [puppeteer](https://github.com/puppeteer/puppeteer) or [selenium](https://github.com/seleniumhq/selenium) and it will become even more powerful when used with [IP hiding techniques](#i-ip-hiding-techniques).
+- You can get each part of the contents through different URLs, not only through the page scrolling ➔ You can do something like using proxy for each request or [AutoThrottle](https://docs.scrapy.org/en/latest/topics/autothrottle.html) (a built-in [scrapy](https://scrapy.org) extension), ...
+
+Updating...
+
+## APPROACH 3. CSR - Client-side Rendering
+
+👉 Check out my implementation using 2 [scraping tools](#scraping-tools) for this approach: [Selenium](./stealth-csr-selenium/) (Deprecated) and [Puppeteer](./stealth-csr-puppeteer/) (Implementing).
+
+Updating...
+
+
+## APPROACH 4. DevTools Console
+
+This is the most simple way, which is to directly write & run JS code in the [DevTools Console](https://developer.chrome.com/docs/devtools/open) of your browser, so it's quite convenient, not required to setup anything.
+
+- You can take a look at this [extremely useful project](https://github.com/jayremnt/facebook-scripts-dom-manipulation) which includes many automation scripts (not just about data extraction) with no Access Token needed for Facebook users by directly manipulating the DOM.
+
+- Here's my example script to collect comments on **a Facebook page when not sign-in**:
+
+```js
+// Go to the page you want to collect, wait until it finishes loading.
+// Open the DevTools Console on the Browser and run the following code
+let csvContents = [['UserId', 'Name', 'Comment']];
+let cmtsSelector = '.userContentWrapper .commentable_item';
+
+// 1. Click see more comments
+// If you want more, just wait until the loading finishes and run this again
+moreCmts = document.querySelectorAll(cmtsSelector + ' ._4sxc._42ft');
+moreCmts.forEach(btnMore => btnMore.click());
+
+// 2. Collect all comments
+comments = document.querySelectorAll(cmtsSelector + ' ._72vr');
+comments.forEach(cmt => {
+ let info = cmt.querySelector('._6qw4');
+ let userId = info.getAttribute('href')?.substring(1);
+ let content = cmt.querySelector('._3l3x>span')?.innerText;
+ csvContents.push([userId, info.innerText, content]);
+});
+csvContents.map(cmt => cmt.join('\t')).join('\n');
+```
+
+
+
+
+ Example result for the script above
+
+
+
+| UserId | Name | Comment |
+| -------------- | -------------- | ---------------------------------- |
+| freedomabcxyz | Freedom | Sau khi dùng |
+| baodendepzai123 | Bảo Huy Nguyễn | nhưng mà thua |
+| tukieu.2001 | Tú Kiều | đang xem hài ai rãnh xem quãng cáo |
+| ABCDE2k4 | Maa Vănn Kenn | Lê Minh Nhất |
+| buikhanhtoanpro | Bùi Khánh Toàn | Haha |
+
+
+
+## Scraping Tools
+
+Updating...
+
+
+## Bypassing Bot Detection (When not sign-in)
+
+Updating...
+
+👉 Highly recommend: https://github.com/niespodd/browser-fingerprinting
+
+### I. IP hiding techniques
+
+
+
+
+ Technique |
+ Speed |
+ Cost |
+ Scale |
+ Anonymity |
+ Other Risks |
+ Additional Notes |
+
+
+
+
+ VPN Service ⭐⭐ ⭐⭐ |
+ Fast, offers a balance of anonymity and speed |
+ Usually paid |
+ - Good for small-scale operations. - May not be suitable for high-volume scraping due to potential IP blacklisting. |
+ - Provides good anonymity and can bypass geo-restriction. - Potential for IP blacklisting/blocks if the VPN's IP range is known to the target site. |
+ - Service reliability varies. - Possible activity logs. |
+ Choose a reputable provider to avoid security risks. |
+
+
+ TOR Network ⭐⭐ |
+ Very slow due to onion routing |
+ Free |
+ - Fine for small-scale, impractical for time-sensitive/ high-volume scraping due to very slow speed. - Consider only for research purposes, not scalable data collection. |
+ - Offers excellent privacy. - Tor exit nodes can be blocked or malicious, like potential for eavesdropping. |
+ - |
+ Slowest choice |
+
+
+ Public Wi-Fi ⭐ |
+ Vary |
+ Free |
+ Fine for small-scale. |
+ Potential for being banned by target sites if scraping is detected. |
+ Potential unsecured networks |
+ Long distance way solution.
|
+
+
+ Mobile Network ⭐⭐ |
+ Relatively fast but slower speeds on some networks |
+ Paid, potential for additional costs. |
+ Using mobile IPs can be effective for small-scale scraping, impractical for large-scale. |
+ Mobile IPs can change but not an anonymous option since it's tied to your personal account. |
+ - |
+ Using own data |
+
+
+ Private/ Dedicated Proxies ⭐⭐⭐ ⭐⭐ (Best) |
+ Fast |
+ Paid |
+ - Best for large-scale operations and professional scraping projects. |
+ Offer better performance and reliability with lower risk of blacklisting. |
+ Vary in quality |
+ - Rotating Proxies are popular choices for scraping as they can offer better speed and a variety of IPs. - You can use this proxy checker tool to assess your proxy quality |
+
+
+ Shared Proxies ⭐⭐⭐ (Free) ⭐⭐ ⭐⭐ (Paid) |
+ Slow to Moderate |
+ Usually Free or cost-effective for low-volume scraping. |
+ Good for basic, small-scale, or non-critical scraping tasks. |
+ Can be overloaded or blacklisted or, encountering already banned IPs. |
+ Potential unreliable/ insecure proxies, especially Free ones. |
+
+
+
+
+**IMPORTANT**: Nothing above is absolutely safe and secure. _Caution is never superfluous_. You will need to research more about them if you want to enhance the security of your data and privacy.
+
+### II. Private/Dedicated Proxies (Most effective IP hiding technique)
+
+As you can conclude from the table above, **Rotating Private/Dedicated Proxies** is the most effective IP hiding technique for **undetectable** and **large-scale** scraping. Below are 2 popular ways to effectively integrate this technique into your scraping process:
+
+
+
+
+ Technique |
+ Speed |
+ Cost |
+ Scale |
+ Anonymity |
+ Additional Notes |
+
+
+
+
+ Residential Rotating Proxies ⭐⭐⭐ ⭐⭐ (Best) |
+ Fast |
+ Paid |
+ Ideal for high-end, large-scale scraping tasks. |
+ - Mimics real user IPs and auto-rotate IPs when using proxy gateways, making detection harder. - Provides high anonymity and low risk of blacklisting/blocks due to legitimate residential IPs. |
+ Consider proxy quality, location targeting, and rotation speed. |
+
+
+ Datacenter Rotating Proxies ⭐⭐ ⭐⭐ |
+ Faster than Residential Proxies |
+ More affordable than Residential Proxies |
+ Good for cost-effective, large-scale scraping. |
+ Less anonymous than Residential Proxies. - Higher risk of being blocked. - Easily detectable due to their datacenter IP ranges. |
+ Consider reputation of the provider and frequency of IP rotation. |
+
+
+
+
+Recently, I experimented my web scraping [npm package](https://www.npmjs.com/package/puppeteer-ecommerce-scraper) with [NodeMaven](https://nodemaven.com/?a_aid=quandang), a **Residential proxy provider** with a focus on IP quality as well as stability, and I think it worked quite well. Below is the proxy quality result that I tested using the [proxy checker tool](https://addons.mozilla.org/en-US/firefox/addon/proxy-checker/) I mentioned [above](#i-ip-hiding-techniques):
+
+![](./assets/nodemaven-test.jpg)
+
+And this is the performance measure of my actual run that I tested with my [scraping package](https://www.npmjs.com/package/puppeteer-ecommerce-scraper):
+
+- **Successful scrape runs**: 96% (over 100 attempts). This result is a quite good.
+ - [NodeMaven](https://nodemaven.com/?a_aid=quandang) already reduced the likelihood of encountering banned or blacklisted IPs through the `IP Quality Filtering` feature.
+ - Another reason is that it can access to over `5M residential IPs` across 150+ countries, a broad range of geo-targeting options.
+ - I also used their `IP Rotation` feature to rotate IPs within a single gateway endpoint, which simplified my scraping setup and provided consistent anonymity.
+- **Average scrape time**: around 1-2 mins/10 pages for complex dynamic loading website (highly dependent on website complexity). While the proxy speeds were generally consistent, there were occasional fluctuations, which is expected in any proxy service.
+- **Sticky Sessions**: 24h+ session durations allowed me to maintain connections and complete scrapes efficiently.
+- **IP block rate** / **Redirect** / **Blank page** in the first run: <4%.
+
+Overall, throughout many runs, the proxies proved to be reliable with minimal downtime or issues. For those interested in trying [NodeMaven](https://nodemaven.com/?a_aid=quandang), you can apply the code `QD2` for an additional 2GB of traffic free with your trial or package purchase.
+
+### II. Browser Settings & Plugins
+
+Updating...
+
diff --git a/assets/nodemaven-test.jpg b/assets/nodemaven-test.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..632cc4b791ffa0613a91892ccbe2f2b03cb94eb8
GIT binary patch
literal 61337
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
B%AWuL
literal 0
HcmV?d00001
diff --git a/assets/token-business.png b/assets/token-business.png
new file mode 100644
index 0000000000000000000000000000000000000000..c5e07b1f86ecc0eaa035fa361bee099fc4b4973f
GIT binary patch
literal 98475
zcmaHSQ*dTcn{I5|wrxA<*h$B>@x`{&9a|lAjE?!mwr$&-oT`~~_0L@GRr_MsUaMX`
zSW(J~(ui<)a3CNch_W&gsvsZ`3m_n%0WeVCZyc<@1iv4kuBy^vAk~uuCmHvdtKWJ^trNu`dKEfX+X!xq~+^8k#g(uN)R`L#oQgLL#gg#NS^4JhQMYbG+OsN<@
z