> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fucksornot.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Anonymous Voting

Vote on content without authentication. Uses browser fingerprinting to prevent vote manipulation.

## Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://fucksornot.com/api/vote/anonymous \
    -H "Content-Type: application/json" \
    -d '{
      "uploadId": "550e8400-e29b-41d4-a716-446655440000",
      "vote": "upvote",
      "clientFingerprint": "abc123def456..."
    }'
  ```

  ```javascript JavaScript theme={null}
  // Generate fingerprint (example using fingerprintjs)
  const fp = await FingerprintJS.load();
  const result = await fp.get();
  const fingerprint = result.visitorId;

  const response = await fetch('https://fucksornot.com/api/vote/anonymous', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      uploadId: '550e8400-e29b-41d4-a716-446655440000',
      vote: 'upvote',
      clientFingerprint: fingerprint
    })
  });
  ```
</CodeGroup>

## Parameters

| Parameter           | Type   | Required | Description              |
| ------------------- | ------ | -------- | ------------------------ |
| `uploadId`          | UUID   | Yes      | The upload to vote on    |
| `vote`              | string | Yes      | `upvote` or `downvote`   |
| `clientFingerprint` | string | Yes      | Browser fingerprint hash |

## Response

```json theme={null}
{
  "success": true,
  "alreadyVoted": false,
  "vote": "upvote"
}
```

If already voted:

```json theme={null}
{
  "success": false,
  "alreadyVoted": true,
  "existingVote": "upvote",
  "message": "You have already voted on this item"
}
```

## Fingerprinting

Anonymous voting uses multiple signals to identify unique visitors:

* Client-provided fingerprint
* IP address (hashed)
* User agent
* Request headers

<Note>
  IP addresses are hashed (SHA-256) and never stored in plain text.
</Note>

<Note>
  Anonymous votes on private uploads are rejected with a `400` error (`"Invalid upload ID"`). Anonymous voting is only available on publicly accessible uploads.
</Note>

<Note>
  Duplicate vote detection is checked server-side via the hashed IP address first, and independently via the `clientFingerprint`. A match on either one is enough to flag the request as `alreadyVoted`.
</Note>

## Vote Mapping

| Anonymous Vote | Equivalent To   |
| -------------- | --------------- |
| `upvote`       | `fucks`         |
| `downvote`     | `does_not_fuck` |

## Rate Limiting

Anonymous votes are limited to **10 requests per minute** per IP address.

## Best Practices

<AccordionGroup>
  <Accordion title="Use a fingerprinting library">
    Libraries like FingerprintJS provide consistent, reliable fingerprints.
  </Accordion>

  <Accordion title="Handle 'already voted' gracefully">
    Check the `alreadyVoted` field to inform users if they've already voted.
  </Accordion>

  <Accordion title="Encourage account creation">
    Authenticated votes are more trusted and less restricted.
  </Accordion>
</AccordionGroup>
