diff --git a/connector/linkedin/linkedin.go b/connector/linkedin/linkedin.go
index df5725b3e1b6642a4faaf82fe2fb9716f3aacffc..1c8312c11e9b4ca4eebfba34e3d498f47e4e2421 100644
--- a/connector/linkedin/linkedin.go
+++ b/connector/linkedin/linkedin.go
@@ -16,7 +16,7 @@ import (
 )
 
 const (
-	apiURL   = "https://api.linkedin.com/v1"
+	apiURL   = "https://api.linkedin.com/v2"
 	authURL  = "https://www.linkedin.com/oauth/v2/authorization"
 	tokenURL = "https://www.linkedin.com/oauth/v2/accessToken"
 )
@@ -38,7 +38,7 @@ func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error)
 				AuthURL:  authURL,
 				TokenURL: tokenURL,
 			},
-			Scopes:      []string{"r_basicprofile", "r_emailaddress"},
+			Scopes:      []string{"r_liteprofile", "r_emailaddress"},
 			RedirectURL: c.RedirectURI,
 		},
 		logger: logger,
@@ -133,11 +133,19 @@ func (c *linkedInConnector) Refresh(ctx context.Context, s connector.Scopes, ide
 
 type profile struct {
 	ID        string `json:"id"`
-	FirstName string `json:"firstName"`
-	LastName  string `json:"lastName"`
+	FirstName string `json:"localizedFirstName"`
+	LastName  string `json:"localizedLastName"`
 	Email     string `json:"emailAddress"`
 }
 
+type emailresp struct {
+	Elements []struct {
+		Handle struct {
+			EmailAddress string `json:"emailAddress"`
+		} `json:"handle~"`
+	} `json:"elements"`
+}
+
 // fullname returns a full name of a person, or email if the resulting name is
 // empty
 func (p profile) fullname() string {
@@ -149,15 +157,50 @@ func (p profile) fullname() string {
 	return fname
 }
 
+func (c *linkedInConnector) primaryEmail(ctx context.Context, client *http.Client) (email string, err error) {
+	req, err := http.NewRequest("GET", apiURL+"/emailAddress?q=members&projection=(elements*(handle~))", nil)
+	if err != nil {
+		return email, fmt.Errorf("new req: %v", err)
+	}
+
+	resp, err := client.Do(req.WithContext(ctx))
+	if err != nil {
+		return email, fmt.Errorf("get URL %v", err)
+	}
+	defer resp.Body.Close()
+
+	body, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return email, fmt.Errorf("read body: %v", err)
+	}
+
+	if resp.StatusCode != http.StatusOK {
+		return email, fmt.Errorf("%s: %s", resp.Status, body)
+	}
+
+	var parsedResp emailresp
+	err = json.Unmarshal(body, &parsedResp)
+	if err == nil {
+		for _, elem := range parsedResp.Elements {
+			email = elem.Handle.EmailAddress
+		}
+	}
+
+	if email == "" {
+		err = fmt.Errorf("email is not set")
+	}
+
+	return email, err
+}
+
 func (c *linkedInConnector) profile(ctx context.Context, client *http.Client) (p profile, err error) {
-	// https://developer.linkedin.com/docs/fields/basic-profile
-	req, err := http.NewRequest("GET", apiURL+"/people/~:(id,first-name,last-name,email-address)", nil)
+	// https://docs.microsoft.com/en-us/linkedin/shared/integrations/people/profile-api
+	// https://docs.microsoft.com/en-us/linkedin/shared/integrations/people/primary-contact-api
+	// https://docs.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/migration-faq#how-do-i-retrieve-the-members-email-address
+	req, err := http.NewRequest("GET", apiURL+"/me", nil)
 	if err != nil {
 		return p, fmt.Errorf("new req: %v", err)
 	}
-	q := req.URL.Query()
-	q.Add("format", "json")
-	req.URL.RawQuery = q.Encode()
 
 	resp, err := client.Do(req.WithContext(ctx))
 	if err != nil {
@@ -177,9 +220,11 @@ func (c *linkedInConnector) profile(ctx context.Context, client *http.Client) (p
 		return p, fmt.Errorf("JSON decode: %v", err)
 	}
 
-	if p.Email == "" {
-		return p, fmt.Errorf("email is not set")
+	email, err := c.primaryEmail(ctx, client)
+	if err != nil {
+		return p, fmt.Errorf("fetching email: %v", err)
 	}
+	p.Email = email
 
 	return p, err
 }