Scrape and Build LinkedIn user profile app with Bright Data and React.js

Learn how to scrape data from LinkedIn using Brightdata and Build a React application

Imagine a situation where you are given a task to build a user dashboard to help keep track of users’ contacts based on their LinkedIn profile.

To do this, you can simply go to LinkedIn to copy as many contacts as possible and then type and format the collected data in a JSON format or the exact format you want for the project. But there is a problem with this approach.

You can end up making so many typos or spend a stupendous amount of time doing repetitive work that can be used to build the actual app.

Better still, you can take the web scraping approach, to manually scrape the data and then export it as a CSV or JSON file. But this is not a scalable option either as many users tend to edit, change, or update their profile regularly leaving the collected data you have out-of-data.

So the question remains, “How do I get an up-to-date user profile dataset and then keep track of the changes?”. Well, in this case, you can make use of Brightdata, a proxy network for bypassing and scraping ready-to-use, up-to-date, structured large datasets.

These datasets can be exported in a CSV or JSON format for easy implementation in your application.

In this blog post, you’ll learn about how to scrape the LinkedIn user profile dataset and download it as a JSON file locally. Additionally, you’ll also learn how to dynamically render each user profile when a particular user is clicked on.

We are going to achieve this using Brightdata and React.js and by the end of this blog, you should be able to use Brightdata to scrape blocked datasets and implement the scraped data in a React application.

Prerequisites

For a better understanding, a basic knowledge of the following is required.

  • React.js
  • Web Scraping

Overview

Here is a preview of what we’ll be building. It’s a simple but feature-rich app that stores LinkedIn user profile contacts.

Click the names to open specific information about each user. 👉 To get started download the GitHub file here.

Now that we have that out of the way, let’s get started.

Create a Bright Data Account

Firstly, we have to create an account with Bright Data, to begin scraping data. Create an account by clicking the Start free with Google button or log in to Bright Data if you already have an account.

You will be directed to the dashboard. Click the datasets & web scraper IDE icon.

Next, scroll down to the Web Scraper IDE section and click Get Started.

Next, from the dialog box, select the first item “LinkedIn Peoples Profile”, then hover and click Use Template.

This will open the web scraper IDE interface as indicated below 👇

Web Scraper IDE Interface

The Web Scraper IDE is made up of different distinct sections for interacting and collecting data.

  • A: See more examples: With this button, you can choose another dataset template from the list of predefined templates
  • B: Add Another Step (Stage): With this button, you can add another stage. This helps to scrape data from multiple pages.
  • C: Help: List of predefined functions to help add extra functionality when collecting dataset.
  • D: Debugging Tools: This tab contains tools for testing, running, and debugging collected datasets before its ready for use.
    • Input: used to add parameters and run tests on collected datasets.
    • Output: This is where a list of collected datasets and their parameter are listed.
    • Children: List of children which will be input sets of the next stage.
    • Run Log: Where collected dataset parameters are logged.
    • Browser Console: Where collectors are logged. Function similarly to the browser console tab.
    • Browser Network: Where network collector requests are displayed. Functions similarly to the browser network tab.
    • Last Errors: Where the latest error information is listed
  • E: input:
    • Add input: To set a new input parameter such as its name and type.
    • Add another input: To add another parameter
    • Preview: To preview the already established parameter.
  • F: Settings:
    • For setting: A set of behaviors for the collector error case
    • Take Screenshots: Take screenshots during the preview test.

With the web scraper IDE we can define how our collected dataset is processed and structured. You can read more on the docs here.

Scrape your first dataset

Now that we have an idea of how the web scraper IDE works and have a collected dataset set up.

Next, go to the preview section and click on the play icon to preview the structure of your collected dataset. This preview section contains HTML elements of how your collected dataset is structured on the webpage.

However, to see the actual browser preview, click on the Pop-out button.

This will open an “about:blank” page with a visual preview of what is listed on the dataset. This is very useful as it gives you a preview of the type of dataset you are retrieving or working with.

From the browser preview, we have a preview of a user profile with different types of data about the user.

Once you are satisfied with your desired data collection head back to the Web Scraper IDE and click on Finish Editing.

This will open the initiate manually tab. Here you will see all the defined parameters for your dataset. These parameters are the individual URLs of the user’s profile we need to build our application.

You can copy any of the URLs listed below and paste it into your browser address bar to see what type of dataset set it contains.

Next, scroll down and click on the start button

This will open the Runs tab. Here our collected dataset will go through a retrieval process. This will take some time depending on the speed of your network.

Notice the downloading animation indicated by the blue arrow.

Once the dataset has been retrieved (downloaded), hover on the Download file option button and click on the option icon, then click on the quick view option.

From the preview dialog box, you can see all the retrieved datasets collected. Next, click on the Download file button to download the dataset. This will enable us to get access to the raw JSON file for local development.

It’s important to note that there are other options for retrieving this same dataset aside from downloading it directly.

To do this, click on the little option button beside the more tabs and select the delivery preferences.

From the Delivery Preferences tab, we can specify how, when, and the type of format we want the dataset to have.

Depending on the type of application you are building this might be just what you need.

However, due to the scope of this tutorial, we will not be covering this section. This is just to highlight that this option exists

React.js set up with Vite

Now that we’ve completed scraping the dataset that we need for building our app. Let’s get our project up and running.

  • Create a folder on your Desktop and name it user-contact, then open it on VS code like so.

  • Still on VS code, click on Ctrl + backtick ( ` ) to open the terminal.
  • Type the command npm create vite@latest to initialize Vite

  • Type dot . and press enter to replace the vite-project name with the project folder as the default name.
  • Select react and press enter

  • Select JavaScript and press enter

  • Type npm install and press enter to scaffold your project. Your terminal should display the following details to show the installation is complete.

Before we run the dev server, we need to install the necessary dependencies needed to build the project. This includes;

  • react-router-dom 6.4: for client-side routing. To install run npm i react-router-dom on the terminal and press enter.
  • feather icons: for adding icons. To install run npm i react-feather on the terminal and press enter. This will install feather icon for react.

Once you have react-router-dom and feather-icons installed. Next, install tailwindcss by following the commands below.

  • Install tailwindcss via npm npm install -D tailwindcss postcss autoprefixer
  • Next, create your tailwind.config.js file and postcss.config.cjs npx tailwindcss init -p

This will generate two files as indicated above.

  • Next, copy and paste the code below on your tailwind.config.js file to Configure your template paths
/** @type {import('tailwindcss').Config} */
export default {
  content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
}
  • Next, delete the default styles in your index.css files then copy and paste the @tailwind directives for each of Tailwind’s layers to your index.css file.
@tailwind base;
@tailwind components;
@tailwind utilities;

Now that we’ve included @tailwind directives, the next thing to do is to include the font family we need for styling the font on the app.

  • Copy and paste the URL for the raleway font to the index.css files as indicated below.
@tailwind base;
@tailwind components;
@tailwind utilities;
 
@import url('https://fonts.googleapis.com/css2?family=Raleway:ital,wght@0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');
  • Next, go to the  tailwind.config.js file and edit it as follows to enable tailwindcss to recognize the font. This will enable us to use it with the tailwindcss utility classes.
/** @type {import('tailwindcss').Config} */
export default {
  content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
  theme: {
    extend: {
      fontFamily: {
        raleway: ['Raleway', 'sans-serif']
      }
    },
  },
  plugins: [],
}

We have now successfully installed tailwindcss in our project. let’s set up the folder structure for rapid development.

Folder structure setup

To set up the folder structure of our project, delete the App.css, App.jsx and react.svg from the project folder. Here is an overview of what the complete folder structure looks like

📁src
   📁apis
      ├── DisplayError.jsx
   📁assets
      ├── alexanie.png
      ├── colorful.jpg
      ├── exception.jpg
   📁components
      ├── ContentList.jsx
   📁layouts
      ├── DisplayContent.jsx
      ├── SideNav.jsx
   ├── DisplayError.jsx
   ├── index.css
   ├── main.jsx
index.html

Copy the images from the completed project on GitHub here.

Creating Routes

Now that we’ve sorted out the folder structure, we need to specify client-side routing. We do this with the help of react-router we’ve just installed.

  • To get started, click the main.jsx file open, delete the import App from './App.jsx’ statement, and import the following functions from react-router-dom as indicated below.
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.css';

import {
	createRoutesFromElements,
  createBrowserRouter,
  Route,
  RouterProvider
} 

from "react-router-dom";
  • Next, create a router function and then parse the createBrowserRouter, createRoutesFromElements as follows. With Route, the URL segments, components, data loaders, mutations, complex layouts, and route nesting are coupled together to achieve client-side routing. This makes it easy to navigate from one route to the other in a single-page application.
const router = createBrowserRouter(
    createRoutesFromElements(
      <Route /> 
      </Route>
    )
  )
  • Next, replace the <App /> component in the ReactDOM.createRoot function with the RouterProvider and then parse the router function to the router props as specified below.
ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>
)

If everything above seems foreign to you, try learning how react-router-dom handles routing.

  • Next, go back to router function and add the path and element props. Inside the element props, parse the HTML tag <p>Hello World!</p> as indicated below.

Now that we have the routing set up, let’s start the dev server to see a live preview of what we’ve been working on.

  • Go to the terminal and type npm run dev then press enter.
  • Next, press control key and click on the dev server path 👉 http://localhost:5173/. You should see the Hello World display as indicated below. 👇

Hurray! 🎉, if you made it this far in this tutorial, congrats. Our app is now live.

While printing Hello World! feels great. There is much into building an app than just plain text, in the section, we are going to be building the Sidebar component. This is where the header, names of users, and footer will reside. For the sake of understanding, we’ll break this into three sections.

  • Header: where the search bar will be placed
  • ContentList: where names of each user will be placed.
  • Footer: Noting special just a simple footer that directs you to my X page 🤓 and you can customize it with your user profile.

Header section

  • Create a folder and component as src/layouts/SideNav.jsx
  • Next, open the SideNav.jsx components, then type the code below.
import {Search} from "react-feather";


export default function SideNav() {
    
  return (
    <>
    <main>
    <aside>
        <section className="bg-slate-100 max-w-[18em] w-[18em] h-[100vh] overflow-y-scroll" id="scrollStyles">
            <nav className="">
                <form className="w-[17em] flex justify-center py-8 px-2 border-b-[1px] border-slate-400 shadow-lg fixed backdrop-blur-sm">
                    <div className="flex bg-white  rounded-xl pl-3 py-2 w-[90%]">
                        <Search className="text-slate-300"/>
                        <input type="text" name="" id="" className="bg-transparent outline-none px-2 mr-4 w-[100%] text-slate-500"/>
                    </div>
                </form>
            </nav>
        </section>
    </aside>

    <aside className="renderOutlet">

    </aside>
</main>

    </>
  )
}

The <section> tag contains all content that goes inside the SideNav components while inside the <nav> tag, we design the heading of the navbar.

  • Next, go to main.jsx Components, import the SideNav Component and change the Hello World to <SideNav /> component as indicated below.
import SideNav from './layouts/SideNav';

  const router = createBrowserRouter(
    createRoutesFromElements(
      <Route path="/" element={<SideNav />}> </Route>
    )
  )

Your app should look just like this 👇

ContentList section

Create a folder as apis and move the downloaded dataset inside the apis folder.

For readability purposes rename the file to mylinkedin.json.

  • Next, create a folder and component as src/component/ContactList.jsx.
  • Next, open the ContactList.jsx component and type the code below
import { NavLink } from 'react-router-dom';
import linkedinData from '../apis/mylinkedin.json';

export default function ContactList() { 
    const activeState = ({ isActive }) => {
        return {
          color: isActive ? "rgb(59 130 246)" : "",
          borderLeft: isActive ? '3px solid rgb(59 130 246)' : ""
        };
      };

    const names = linkedinData.map((name)=> (
            <NavLink key={name.id} className="p-2 my-3 block font-raleway hover:bg-blue-300/20 transition-all rounded-xl" style={activeState} to={`profile/${name.id}`}>
              <span>{name.name}</span>
            </NavLink>
        ))

  return (
    <>
        <main>
            {names}
        </main>
    </>
  )
}

What we are doing here is simply mapping through the arrays of object data and returning all the names in an anchor tag.

  • Next, go to the SideNav component and create a div and import the ContactList.jsx as indicated below.
import {Search} from "react-feather";
import ContactList from "../components/ContactList";

export default function SideNav() {
 
  return (
    <>
    <main className="flex">
    <aside>
        <section className="bg-slate-100 max-w-[18em] w-[18em] h-[100vh] overflow-y-scroll" id="scrollStyles">
            <nav className="">
                <form className="w-[17em] flex justify-center py-8 px-2 border-b-[1px] border-slate-400 shadow-lg fixed backdrop-blur-sm">
                    {/* some other code...  */}
                </form>
            </nav>

            <div className="p-4 mt-[8em]">
	👉             <ContactList />
            </div>

        </section>
    </aside>
    <aside className="renderOutlet">
       
    </aside>
</main>

    </>
  )
}

Your app should have all the names listed as shown below.

Download these images and move them into the assets folder. Next, go to the SideNav component and type the code below.

import {Search} from "react-feather";
import ContactList from "../components/ContactList";
import alexImages from "../assets/alexanie.png";
import { Link } from "react-router-dom";


export default function SideNav() {
    const alexData = {
        firstName: 'Alex',
        lastName: 'Anie',
        img: alexImages,
        x: 'https://twitter.com/alexanie_'
    }
  return (
    <>
    <main>
    <aside>
        <section className="bg-slate-100 max-w-[18em] w-[18em] h-[100vh] overflow-y-scroll" id="scrollStyles">
            <nav>
                {/* some other code... */}
            </nav>

            <div className="p-4 mt-[8em]">
                <ContactList />
            </div>

            <div className="absolute bottom-0 bg-white w-[17em] py-2 px-8 hover:bg-blue-200 transition-all ease-linear">
                <Link to={alexData.x} className="flex justify-start" target="_blank">
                    <div className="w-[2.5em] h-[2.5em] bg-slate-200 rounded-full py-2 px-2">
                        <img src={alexData.img} alt=""  className="w-full rounded-full"/>
                    </div>
                    <span className="font-raleway font-semibold my-2 mx-4 text-blue-600">{`${alexData.firstName} ${alexData.lastName}`}</span>
                </Link>
            </div>
        </section>
    </aside>
    <aside className="renderOutlet">
    
    </aside>
</main>

    </>
  )
}

Your app should have the little footer below 🤓

Handling Error in your Application - errorElement

If you click on any of the names on the SideNav, your browser will display an error page. For example, click on the first name khon noma and notice how react-router throws an error page.

React Router refers to this as Not Found Page or simply 404. This means the page we are trying to access does not exist or is not specified on the path. To handle this we use errorElement.

With the errorElement, we can create a page that displays to the users what went wrong when a particular error occurs such as 404, and indicate on the page what action the user should take.

  • To do this, simply create a new component as src/DisplayError.jsx.
  • open the DisplayError.jsx component and type the code below.
import { useRouteError, Link } from "react-router-dom"
import imgError from "./assets/exception.jpg";
export default function DisplayError() {
    const error = useRouteError();

  return (
    <>
        <main style={{
            width: "100vw",
            height: "100vh",
            position: "relative",
            backgroundImage: `url('${imgError}')`,
            backgroundPosition: "center center",
            backgroundSize: "cover",
            backgroundRepeat: "no-repeat",
        }}>

                <div className="absolute top-[8em] left-[40%] ">
                    <p className="text-[10em] text-red-600 font-mono font-extrabold">{error.status}</p>
                </div>

            <div className="absolute bottom-12 left-[35%]">
                <p className="font-mono text-center text-slate-700 bg-slate-100 px-2 rounded-full">click <Link to="/" className="text-red-600">here</Link> to go back to home page</p>
                <p className="font-mono text-center text-slate-700 bg-slate-100 px-2 rounded-full">{error.error.message}</p
            </div>
        </main>
    </>
  )
}

Note that we are using a hook from react-router called useRouteError that helps handle the error that occurs during an action.

  • Next, go to the main.jsx component import the DisplayError component and add it to Route.
import DisplayError from './DisplayError';

  const router = createBrowserRouter(
    createRoutesFromElements(                            👇
      <Route path="/" element={<SideNav />} errorElement={<DisplayError />}> </Route>
    )
  )

Now click any of the names and see what happens. You should see something like this.

The page above displays an error code of 404 letting the user know that the page can not be found with a text redirecting them to the home page.

Click on the text that says click here to go back to home page.

Implementing Dynamic Segment

The main idea of our application is to create an app with a list of users generated from LinkedIn. The app contains a list of user names and upon clicking review the details of each user. To achieve this behavior, we need to implement what is referred to as dynamic segment using the useParams hook.

  • In the layouts folder create a component as DisplayContent.jsx
  • Next, type the code below inside the DisplayContent component
import { BookOpen, MapPin } from "react-feather";
import  linkedinData  from "../apis/mylinkedin.json";
import bgImg from "../assets/colorful.jpg";
import { Link, useParams } from "react-router-dom";

export default function DisplayContent() {
    const {profileId} = useParams();

    const profile = linkedinData.find(profile => profile.id === profileId);

    if(!profile){
      return <p>Profile not found</p>
    }

    return (
    <div className="bg-slate-200 ">
      {
        profile && (
          <>
          <section className="grid grid-cols-6 gap-8 w-[95%] mt-0 mx-auto overflow-y-scroll h-[100vh] pr-[1em]" id="scrollStyles">
            {/* Header */}
            <aside className="col-span-4 rounded-2xl bg-white mt-12 relative">
              <div className="w-full h-[10em] bg-blue-700 rounded-t-2xl">
                <img src={bgImg} alt="" className="w-full h-full rounded-t-2xl object-left-bottom" />
              </div>
              <div className="w-[7em] h-[7em] absolute top-[6em] left-12"> 
                <img src={profile.avatar} alt="" className="rounded-full w-full h-full border-4 border-white"/>
              </div>
              <div className="py-[4em] px-[2em] grid grid-cols-6 gap-8">
                  <div className="col-span-2">
                    <h1 className="text-xl font-bold mb-2">{profile.name}</h1>
                    <p className="text-sm">
                      <BookOpen size={12} className="inline-block"/>
                      <em className="not-italic inline-block">{profile.position}</em></p>
                    <p className="text-sm mt-4">
                      <MapPin size={12} className="text-slate-500 inline"/>
                      <em className="not-italic text-slate-600 inline-block pl-2">{profile.region}</em>
                    </p>
                    <Link to={profile.url} target="_blank" className="text-sm mt-2 block text-blue-700 font-bold hover:text-blue-500">Connect on Linkedin</Link>
                  </div>

                  <div className="col-span-4">
                    <div>
                      <h2 className="font-bold text-xl mb-4">
                        About
                      </h2>
                      <p className="text-sm">
                        {profile.about}
                      </p>
                    </div>
                    <p>
                      <span className="text-sm mt-2 text-blue-700 font-bold  inline-block cursor-default">following <em className="not-italic text-slate-500 font-normal px-2">{profile.following}</em></span>
                      <span className="text-sm mt-2 text-blue-700 font-bold  inline-block cursor-default">followers <em className="not-italic text-slate-500 font-normal px-2">{profile.followers}</em></span>
                      <span className="text-sm mt-2 text-blue-700 font-bold inline-block cursor-default">connections <em className="not-italic text-slate-500 font-normal px-2">{profile.connections}</em></span>
                    </p>
                  </div>
              </div>
            </aside>

              {/* Experience */}
              <aside className="col-span-2 bg-white rounded-2xl mt-12 py-8 px-4">
              <h2 className="font-bold text-xl pb-3">Experience</h2>
              {
                profile.experience.map((ele, index)=> (
                  <>
                  <section className="flex gap-x-4 mt-8">
                  <div className="w-[50px] h-[50px] bg-red-600 rounded-xl">
                    <p className="text-center font-block text-3xl mt-1">{ele.title.charAt(0)}</p>
                  </div>
                    <div key={index}>
                      <p className="font-bold text-sm">{ele.title}</p>
                      <p><span className="text-slate-600 text-sm">Duration</span> <span className="text-sm">{ele.duration}</span></p>
                    </div>
                  </section>
                  </>
                ))
              }
              </aside>

            {/* Posts */}
            <aside className="col-span-4 bg-white rounded-2xl py-8 px-4  h-[fit-content]">
              <h2 className="font-bold text-xl pb-3">Posts</h2>
              <div className="flex gap-4">
                {
                  profile.posts.map((ele)=>(
                    <>
                          <Link to={ele.link} className="">
                              <div>
                                <img src={ele.img} alt={ele.title} className="rounded-xl" />
                              </div>
                              <p className="mt-4 font-bold">{ele.title}</p>
                              <p className="text-slate-500 my-2">{ele.attribution}</p>
                              <p className="text-sm">{ele.created_at}</p>
                          </Link>
                    </>
                  ))
                }
                </div>
            </aside>

            {/* Education */}
            <aside className="col-span-2 bg-white rounded-2xl py-8 px-4 mb-[8em] h-[fit-content]">
            
            <h2 className="font-bold text-xl pb-3">Education</h2>
                {
                  profile.education.map((ele)=>(
                    <>
                      <div className="flex">
                        <div className="w-[50px] h-[50px] bg-blue-600 rounded-xl text-white">
                          <p className="text-center font-block text-3xl mt-1">{ele.title.charAt(0)}</p>
                        </div>
                
                        <Link to={ele.url} target="_blank" className="ml-4 mb-8">
                            <div>
                              <h2 className="font-bold">{ele.title}</h2>
                            </div>
                            <p className="my-2"><span className="text-slate-700 inline-block pr-4 text-sm">Degree</span><span className="text-sm">{ele.degree}</span></p>
                            <p><span className="text-slate-700 inline-block pr-4 text-sm">Field</span><span className="text-sm">{ele.field}</span></p>
                            <p><span className="text-sm mt-4">Start Year {ele.start_year}</span> | <span className="text-sm">End Year {ele.end_year}</span></p>
                        </Link>
                      </div>
                    </>
                  ))
                }
            </aside>
          </section>
          </>
        )
      }
    </div>
  )
}

When we click on a particular user name from the SideNav, it appears on the address bar. So the find() method checks if the user. id present in the LinkedIn data matches with the dynamic segment (params) parent in the URL (address bar) and if this is true. The specific user data from the LinkedIn data should rendered on the page.

If the LinkedIn data does not match, <p>profile not found</p> should be printed on the page.

  • Next, go to main.jsx, import the DisplayContent component, and add it to Route.
import DisplayContent from './layouts/DisplayContent';

  const router = createBrowserRouter(
    createRoutesFromElements(
      <Route path="/" element={<SideNav />} errorElement={<DisplayError />}> 
         <Route path='profile/:profileId' element={<DisplayContent />} /> 
      </Route>
    )
  )
  • Since the DisplayContent is a nested route, we need to render it as an Outlet.
  • Go to the SideNav.jsx, import the Outlet component from react-router-dom and render it inside the renderOutlet tag.
👉 import { Link, Outlet } from "react-router-dom";

 <main className="flex">
    <aside>
        <section className="bg-slate-100 max-w-[18em] w-[18em] h-[100vh] overflow-y-scroll" id="scrollStyles">
            {/* some other code...  */}
        </section>
    </aside>
    <aside className="renderOutlet">
       👉   <Outlet />
    </aside>
</main>

Now, click on any of the names in the SideNav. Your app should look like this 👇

Styling the Scrollbar of the application

The page scrollbar still keeps the default styling. Let’s add some styling to make it look nice.

  • Go to the SideNav and scrollStyles to the id attribute on the section tag.
<main className="flex">
    <aside>
     👉   <section id="scrollStyles" className="bg-slate-100 max-w-[18em] w-[18em] h-[100vh] overflow-y-scroll">
             {/* Some other code... */}
        </section>
    </aside>
 {/* Some other code... */}
 
</main>
  • Next, go to the DisplayContent.jsx and scrollStyles to the id attribute on the section tag.
<section  id="scrollStyles" className="grid grid-cols-6 gap-8 w-[95%] mt-0 mx-auto overflow-y-scroll h-[100vh] pr-[1em]">
</section>
  • Next, go to the index.html file and add the style rules.
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>User Content</title>
    <style>
      body {
        overflow: hidden;
      }
  
      #scrollStyles::-webkit-scrollbar {
        width: 10px;
      }
  
      #scrollStyles::-webkit-scrollbar-track {
        background: #f1f1f1;
      }
  
      #scrollStyles::-webkit-scrollbar-thumb {
        background: #888; 
        border-radius: 5px;
      }
  
      #scrollStyles::-webkit-scrollbar-thumb:hover {
        background: #555;
      }
    </style>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.jsx"></script>
  </body>
</html>

Your scrollbar should look like this on your app.

Conclusion

We have concluded scrape and build Linkedin user profile app with Bright data and React.js.

Using Bright data can help reduce the tedious task of sourcing for data by using the already established data from any platform.

Continue Learning

Discover more articles on similar topics