# Send DM for Linkedin (`addeus/send-dm`) Actor

Send personalized Direct Messages (DMs) to your LinkedIn connections in bulk. Supports variables like {firstName} for customization. Features randomized delays and proxy support to ensure account safety. Best for 1st-degree outreach.

- **URL**: https://apify.com/addeus/send-dm.md
- **Developed by:** [Addeus](https://apify.com/addeus) (community)
- **Categories:** Lead generation, Automation, Social media
- **Stats:** 75 total users, 2 monthly users, 100.0% runs succeeded, 3 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.01 / actor start

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## LinkedIn Send DM Actor

Actor Apify pour automatiser l'envoi de messages privés (DMs) sur LinkedIn en utilisant Puppeteer.

### Fonctionnalités

- **Envoi automatique de DMs** sur n'importe quel profil LinkedIn
- **SAFETY CHECK CRITIQUE** - Vérifie que le message est envoyé à la bonne personne avant l'envoi
- **Authentification par cookies** (li\_at) - pas besoin d'OAuth
- **Workflow complet** : Visite du profil → Clic sur "Message" → Vérification du destinataire → Saisie du message → Envoi
- **Détection intelligente** des boutons avec plusieurs stratégies
- **Anti-détection** - masque les flags webdriver
- **Gestion d'erreurs robuste**

### Input Parameters

| Paramètre     | Type   | Requis | Description                                                |
| ------------- | ------ | ------ | ---------------------------------------------------------- |
| `profileUrl`  | String | ✅ Oui | L'URL complète du profil LinkedIn à qui envoyer le message |
| `messageText` | String | ✅ Oui | Le texte de votre message privé                            |
| `liAtCookie`  | String | ✅ Oui | Cookie d'authentification LinkedIn (li\_at)                 |
| `userAgent`   | String | ❌ Non | User-Agent personnalisé (défaut: Chrome 131 Windows)       |
| `jsessionid`  | String | ❌ Non | Cookie JSESSIONID optionnel                                |

#### Exemple d'Input

```json
{
    "profileUrl": "https://www.linkedin.com/in/johndoe/",
    "messageText": "Hi John! I came across your profile and would love to connect. I'm particularly interested in your work on AI and machine learning.",
    "liAtCookie": "AQEDATxxxxxx..."
}
```

### Comment Obtenir Vos Cookies

#### Cookie li\_at (REQUIS)

1. Ouvre ton navigateur et connecte-toi sur LinkedIn
2. Ouvre les DevTools (F12)
3. Va dans **Application** → **Cookies** → **https://www.linkedin.com**
4. Trouve le cookie `li_at` et copie sa valeur complète

### Output

```json
{
    "profileUrl": "https://www.linkedin.com/in/johndoe/",
    "success": true,
    "message": "DM sent successfully to John Doe",
    "recipientName": "John Doe",
    "messageText": "Hi John! I came across your profile...",
    "timestamp": "2025-10-16T14:30:00.000Z"
}
```

### 🛡️ Safety Check (CRITIQUE!)

L'actor implémente un **double contrôle de sécurité** pour éviter d'envoyer des messages à la mauvaise personne :

1. **Extraction du nom** : Lit le nom de la personne sur la page de profil visitée
2. **Vérification avant envoi** : Après avoir cliqué sur "Message", compare le nom dans la fenêtre de conversation avec le nom du profil
3. **Blocage en cas d'erreur** : Si les noms ne correspondent pas, l'envoi est annulé avec une erreur `SAFETY CHECK FAILED`

**Exemple d'erreur de sécurité** :

```
SAFETY CHECK FAILED: Expected to message "John Doe" but conversation is with "Jane Smith"
```

Cette vérification vous protège contre les erreurs d'envoi accidentelles!

### Workflow de l'Actor

1. **Navigue** vers le profil LinkedIn
2. **Extrait le nom** de la personne sur le profil
3. **Trouve et clique** sur le bouton "Message" ou "Envoyer un message"
4. **Vérifie** que la conversation ouverte correspond bien au profil visité (SAFETY CHECK)
5. **Tape** votre message dans l'éditeur
6. **Clique** sur "Envoyer" (Send)
7. **Retourne** le résultat avec le nom du destinataire confirmé

### Architecture Technique

#### Stratégies de Détection

##### Bouton Message

- `button[aria-label*="Message"]`
- `button[aria-label*="Envoyer un message"]`
- `button.pvs-profile-actions__action[aria-label*="Message"]`
- `button.message-anywhere-button`
- XPath: `//button[contains(., 'Message')]`

##### Champ de Message

- `div.msg-form__contenteditable[contenteditable="true"]`
- `div[contenteditable="true"][role="textbox"]`
- `div.msg-form__msg-content-container .ql-editor`

##### Bouton Envoyer

- `button.msg-form__send-button`
- `button[type="submit"].msg-form__send-button`
- `button[aria-label*="Send"]`
- `button[aria-label*="Envoyer"]`

### Notes Importantes

#### Sécurité & Authentification

- Le cookie `li_at` est ta session LinkedIn - **garde-le secret**
- Les cookies expirent - renouvelle-les si erreur d'authentification

#### Limitations LinkedIn

- **Connexion requise** : Tu dois être connecté à la personne ou avoir un accès InMail
- **Limites d'envoi** : LinkedIn limite le nombre de messages que tu peux envoyer par jour
- **Détection de spam** : Évite d'envoyer des messages identiques à plusieurs personnes

#### Rate Limiting

- LinkedIn peut limiter les actions automatisées trop fréquentes
- Recommandé: espacer les DMs (quelques minutes entre chaque)
- Utilise avec modération pour éviter restrictions de compte

#### Bonnes Pratiques

- ✅ Personnalise chaque message
- ✅ Attends au moins 2-3 minutes entre chaque DM
- ✅ Ne dépasse pas 20-30 DMs par jour
- ❌ N'envoie pas de messages de spam
- ❌ N'utilise pas pour du marketing agressif

#### Légal & CGU

- Cet actor est à des fins **éducatives et de test**
- L'automatisation peut violer les CGU de LinkedIn
- **Utilise à tes propres risques**

### Développement Local

#### Installation

```bash
cd send-dm
npm install
```

#### Test Local

Crée un fichier `input.json`:

```json
{
    "profileUrl": "https://www.linkedin.com/in/username/",
    "messageText": "Your message here",
    "liAtCookie": "YOUR_LI_AT_COOKIE"
}
```

Lance:

```bash
npm start
```

### Dépendances

- **Apify SDK** v3.1.0+
- **Puppeteer** v24.0.0+
- **Node.js** 20.0.0+

### Troubleshooting

#### "Message button not found"

- L'URL du profil est peut-être incorrecte
- Le profil peut ne pas exister ou être privé
- Tu n'es peut-être pas connecté à cette personne (nécessite connexion ou InMail)

#### "Message input not found"

- La fenêtre de message met peut-être plus de temps à charger
- LinkedIn peut avoir changé l'interface
- Essaye d'augmenter les délais dans le code

#### "Send button not found or not enabled"

- Le message est peut-être trop court
- LinkedIn peut nécessiter une action supplémentaire (captcha, vérification)
- Le bouton peut ne pas être activé (message vide ou en cours de traitement)

#### "You've reached your weekly invitation limit"

- Tu as atteint la limite de messages LinkedIn
- Attends quelques jours avant de réessayer
- Privilégie les messages aux personnes déjà connectées

### License

ISC

***

**Créé avec ❤️ pour Apify**

# Actor input Schema

## `profileUrl` (type: `string`):

The full URL of the LinkedIn profile you want to message

## `messageText` (type: `string`):

The text of your direct message

## `liAtCookie` (type: `string`):

Your LinkedIn authentication cookie (li\_at). You can find it in your browser's cookies for linkedin.com

## `userAgent` (type: `string`):

The User-Agent string to use (REQUIRED)

## Actor input object example

```json
{
  "profileUrl": "https://www.linkedin.com/in/username/",
  "messageText": "Hi! I'd like to connect with you regarding...",
  "liAtCookie": "AQEDATxxxxxx...",
  "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("addeus/send-dm").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("addeus/send-dm").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call addeus/send-dm --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,addeus/send-dm"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/1vfEpwG9nUfGUddug/builds/GTNuurLHb7AilXqnI/openapi.json
