tech-stack-lookup 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tech_stack_lookup-0.1.0/LICENSE +5 -0
- tech_stack_lookup-0.1.0/PKG-INFO +100 -0
- tech_stack_lookup-0.1.0/README.md +83 -0
- tech_stack_lookup-0.1.0/pyproject.toml +23 -0
- tech_stack_lookup-0.1.0/setup.cfg +4 -0
- tech_stack_lookup-0.1.0/tech_stack_lookup/__init__.py +6 -0
- tech_stack_lookup-0.1.0/tech_stack_lookup/client.py +112 -0
- tech_stack_lookup-0.1.0/tech_stack_lookup/exceptions.py +13 -0
- tech_stack_lookup-0.1.0/tech_stack_lookup.egg-info/PKG-INFO +100 -0
- tech_stack_lookup-0.1.0/tech_stack_lookup.egg-info/SOURCES.txt +11 -0
- tech_stack_lookup-0.1.0/tech_stack_lookup.egg-info/dependency_links.txt +1 -0
- tech_stack_lookup-0.1.0/tech_stack_lookup.egg-info/requires.txt +1 -0
- tech_stack_lookup-0.1.0/tech_stack_lookup.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ApiVault Labs
|
|
4
|
+
|
|
5
|
+
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. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tech-stack-lookup
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for Tech Stack Lookup on Apify. Find websites by technologies, market signals and public contact availability through the hosted Apify Actor.
|
|
5
|
+
Author: ApiVault Labs
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/apivault-labs/tech-stack-lookup-python
|
|
8
|
+
Project-URL: Documentation, https://github.com/apivault-labs/tech-stack-lookup-python#readme
|
|
9
|
+
Project-URL: Apify Actor, https://apify.com/apivault_labs/tech-stack-lookup
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/apivault-labs/tech-stack-lookup-python/issues
|
|
11
|
+
Keywords: tech-stack,technology-lookup,website-leads,sales-intelligence,b2b-leads,apify,python-sdk
|
|
12
|
+
Requires-Python: >=3.9
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: requests>=2.31.0
|
|
16
|
+
Dynamic: license-file
|
|
17
|
+
|
|
18
|
+
# Tech Stack Lookup — Python SDK
|
|
19
|
+
|
|
20
|
+
Python client for the [Tech Stack Lookup Apify Actor](https://apify.com/apivault_labs/tech-stack-lookup). Send public Actor inputs, wait for the hosted run, and receive clean Dataset rows without maintaining scraping infrastructure.
|
|
21
|
+
|
|
22
|
+
[](https://apify.com/apivault_labs/tech-stack-lookup)
|
|
23
|
+
[](https://www.python.org/)
|
|
24
|
+
[](LICENSE)
|
|
25
|
+
|
|
26
|
+
## Results
|
|
27
|
+
|
|
28
|
+
- Technology and category targeting
|
|
29
|
+
- Country and vertical filters
|
|
30
|
+
- Public contact availability filters
|
|
31
|
+
- Stable sorting, pagination and count previews
|
|
32
|
+
|
|
33
|
+
The repository exposes only the Actor's public input and output contract. Data selection and processing remain inside the hosted Actor.
|
|
34
|
+
|
|
35
|
+
## Install
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install git+https://github.com/apivault-labs/tech-stack-lookup-python.git
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Create an Apify token at [Console → Integrations](https://console.apify.com/account/integrations), then:
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from tech_stack_lookup import TechStackLookupClient
|
|
45
|
+
|
|
46
|
+
client = TechStackLookupClient(api_token="apify_api_xxxxxx")
|
|
47
|
+
rows = client.run({'mode': 'find',
|
|
48
|
+
'technologies': ['Shopify'],
|
|
49
|
+
'country': ['US'],
|
|
50
|
+
'hasEmail': True,
|
|
51
|
+
'maxItems': 100})
|
|
52
|
+
print(rows[0] if rows else "No results")
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
You can set `APIFY_API_TOKEN` instead of passing the token in code.
|
|
56
|
+
|
|
57
|
+
## Public input options
|
|
58
|
+
|
|
59
|
+
| Field | Type | Default | Description |
|
|
60
|
+
|---|---|---|---|
|
|
61
|
+
| `mode` | `string` | `find` | Find matching websites or inspect supplied domains. |
|
|
62
|
+
| `domains` | `array` | `[]` | Domains to inspect in lookup mode. |
|
|
63
|
+
| `technologies` | `array` | `[]` | Technology names to include. |
|
|
64
|
+
| `matchMode` | `string` | `any` | Match any or all selected technologies. |
|
|
65
|
+
| `excludeTechnologies` | `array` | `[]` | Technology names to exclude. |
|
|
66
|
+
| `category` | `array` | `[]` | Technology categories to include. |
|
|
67
|
+
| `country` | `array` | `[]` | ISO-2 country codes. |
|
|
68
|
+
| `vertical` | `array` | `[]` | Business verticals to include. |
|
|
69
|
+
| `hasEmail` | `boolean` | `False` | Return records with a public email. |
|
|
70
|
+
| `hasPhone` | `boolean` | `False` | Return records with a public phone. |
|
|
71
|
+
| `sortBy` | `string` | `` | Public field used to order results. |
|
|
72
|
+
| `sortDesc` | `boolean` | `True` | Return highest values first. |
|
|
73
|
+
| `dedupeByDomain` | `boolean` | `True` | Return each root domain once. |
|
|
74
|
+
| `outputPreset` | `string` | `essential` | Choose a public result layout. |
|
|
75
|
+
| `countOnly` | `boolean` | `False` | Return a count preview instead of rows. |
|
|
76
|
+
| `maxItems` | `integer` | `100` | Maximum number of returned rows. |
|
|
77
|
+
| `offset` | `integer` | `0` | Rows to skip for pagination. |
|
|
78
|
+
|
|
79
|
+
The complete, versioned schema is also available on the [Actor page](https://apify.com/apivault_labs/tech-stack-lookup).
|
|
80
|
+
|
|
81
|
+
## Pricing
|
|
82
|
+
|
|
83
|
+
Pay per delivered result through Apify, starting around **$7/1,000 results** on paid tiers. Free-plan pricing and platform usage can differ; check the Actor page before large runs.
|
|
84
|
+
|
|
85
|
+
## Examples
|
|
86
|
+
|
|
87
|
+
- `examples/quickstart.py` — first run
|
|
88
|
+
- `examples/bulk_analysis.py` — expand a target list
|
|
89
|
+
- `examples/export_csv.py` — save flat result fields
|
|
90
|
+
- `examples/save_json.py` — preserve nested output
|
|
91
|
+
- `examples/cost_estimate.py` — estimate result-event charges
|
|
92
|
+
- `examples/environment_token.py` — keep credentials out of code
|
|
93
|
+
|
|
94
|
+
## Architecture and privacy
|
|
95
|
+
|
|
96
|
+
This repository is intentionally a thin API client. Collection, retries, analysis and billing run inside the hosted Apify Actor. No private implementation, credentials, scoring weights or infrastructure configuration are included.
|
|
97
|
+
|
|
98
|
+
## License
|
|
99
|
+
|
|
100
|
+
MIT. The hosted Actor is a separate paid service governed by Apify terms.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Tech Stack Lookup — Python SDK
|
|
2
|
+
|
|
3
|
+
Python client for the [Tech Stack Lookup Apify Actor](https://apify.com/apivault_labs/tech-stack-lookup). Send public Actor inputs, wait for the hosted run, and receive clean Dataset rows without maintaining scraping infrastructure.
|
|
4
|
+
|
|
5
|
+
[](https://apify.com/apivault_labs/tech-stack-lookup)
|
|
6
|
+
[](https://www.python.org/)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
## Results
|
|
10
|
+
|
|
11
|
+
- Technology and category targeting
|
|
12
|
+
- Country and vertical filters
|
|
13
|
+
- Public contact availability filters
|
|
14
|
+
- Stable sorting, pagination and count previews
|
|
15
|
+
|
|
16
|
+
The repository exposes only the Actor's public input and output contract. Data selection and processing remain inside the hosted Actor.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install git+https://github.com/apivault-labs/tech-stack-lookup-python.git
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Create an Apify token at [Console → Integrations](https://console.apify.com/account/integrations), then:
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
from tech_stack_lookup import TechStackLookupClient
|
|
28
|
+
|
|
29
|
+
client = TechStackLookupClient(api_token="apify_api_xxxxxx")
|
|
30
|
+
rows = client.run({'mode': 'find',
|
|
31
|
+
'technologies': ['Shopify'],
|
|
32
|
+
'country': ['US'],
|
|
33
|
+
'hasEmail': True,
|
|
34
|
+
'maxItems': 100})
|
|
35
|
+
print(rows[0] if rows else "No results")
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
You can set `APIFY_API_TOKEN` instead of passing the token in code.
|
|
39
|
+
|
|
40
|
+
## Public input options
|
|
41
|
+
|
|
42
|
+
| Field | Type | Default | Description |
|
|
43
|
+
|---|---|---|---|
|
|
44
|
+
| `mode` | `string` | `find` | Find matching websites or inspect supplied domains. |
|
|
45
|
+
| `domains` | `array` | `[]` | Domains to inspect in lookup mode. |
|
|
46
|
+
| `technologies` | `array` | `[]` | Technology names to include. |
|
|
47
|
+
| `matchMode` | `string` | `any` | Match any or all selected technologies. |
|
|
48
|
+
| `excludeTechnologies` | `array` | `[]` | Technology names to exclude. |
|
|
49
|
+
| `category` | `array` | `[]` | Technology categories to include. |
|
|
50
|
+
| `country` | `array` | `[]` | ISO-2 country codes. |
|
|
51
|
+
| `vertical` | `array` | `[]` | Business verticals to include. |
|
|
52
|
+
| `hasEmail` | `boolean` | `False` | Return records with a public email. |
|
|
53
|
+
| `hasPhone` | `boolean` | `False` | Return records with a public phone. |
|
|
54
|
+
| `sortBy` | `string` | `` | Public field used to order results. |
|
|
55
|
+
| `sortDesc` | `boolean` | `True` | Return highest values first. |
|
|
56
|
+
| `dedupeByDomain` | `boolean` | `True` | Return each root domain once. |
|
|
57
|
+
| `outputPreset` | `string` | `essential` | Choose a public result layout. |
|
|
58
|
+
| `countOnly` | `boolean` | `False` | Return a count preview instead of rows. |
|
|
59
|
+
| `maxItems` | `integer` | `100` | Maximum number of returned rows. |
|
|
60
|
+
| `offset` | `integer` | `0` | Rows to skip for pagination. |
|
|
61
|
+
|
|
62
|
+
The complete, versioned schema is also available on the [Actor page](https://apify.com/apivault_labs/tech-stack-lookup).
|
|
63
|
+
|
|
64
|
+
## Pricing
|
|
65
|
+
|
|
66
|
+
Pay per delivered result through Apify, starting around **$7/1,000 results** on paid tiers. Free-plan pricing and platform usage can differ; check the Actor page before large runs.
|
|
67
|
+
|
|
68
|
+
## Examples
|
|
69
|
+
|
|
70
|
+
- `examples/quickstart.py` — first run
|
|
71
|
+
- `examples/bulk_analysis.py` — expand a target list
|
|
72
|
+
- `examples/export_csv.py` — save flat result fields
|
|
73
|
+
- `examples/save_json.py` — preserve nested output
|
|
74
|
+
- `examples/cost_estimate.py` — estimate result-event charges
|
|
75
|
+
- `examples/environment_token.py` — keep credentials out of code
|
|
76
|
+
|
|
77
|
+
## Architecture and privacy
|
|
78
|
+
|
|
79
|
+
This repository is intentionally a thin API client. Collection, retries, analysis and billing run inside the hosted Apify Actor. No private implementation, credentials, scoring weights or infrastructure configuration are included.
|
|
80
|
+
|
|
81
|
+
## License
|
|
82
|
+
|
|
83
|
+
MIT. The hosted Actor is a separate paid service governed by Apify terms.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=64", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "tech-stack-lookup"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python SDK for Tech Stack Lookup on Apify. Find websites by technologies, market signals and public contact availability through the hosted Apify Actor."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
authors = [{ name = "ApiVault Labs" }]
|
|
12
|
+
requires-python = ">=3.9"
|
|
13
|
+
dependencies = ["requests>=2.31.0"]
|
|
14
|
+
keywords = ["tech-stack", "technology-lookup", "website-leads", "sales-intelligence", "b2b-leads", "apify", "python-sdk"]
|
|
15
|
+
|
|
16
|
+
[project.urls]
|
|
17
|
+
Homepage = "https://github.com/apivault-labs/tech-stack-lookup-python"
|
|
18
|
+
Documentation = "https://github.com/apivault-labs/tech-stack-lookup-python#readme"
|
|
19
|
+
"Apify Actor" = "https://apify.com/apivault_labs/tech-stack-lookup"
|
|
20
|
+
"Bug Tracker" = "https://github.com/apivault-labs/tech-stack-lookup-python/issues"
|
|
21
|
+
|
|
22
|
+
[tool.setuptools.packages.find]
|
|
23
|
+
include = ["tech_stack_lookup*"]
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"""Python SDK for the hosted Tech Stack Lookup Apify Actor."""
|
|
2
|
+
from .client import TechStackLookupClient
|
|
3
|
+
from .exceptions import TechStackLookupError, AuthenticationError, ActorRunError, ActorTimeoutError
|
|
4
|
+
|
|
5
|
+
__version__ = "0.1.0"
|
|
6
|
+
__all__ = ["TechStackLookupClient", "TechStackLookupError", "AuthenticationError", "ActorRunError", "ActorTimeoutError"]
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"""Thin synchronous client for the Tech Stack Lookup Apify Actor."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import time
|
|
6
|
+
from typing import Any, Mapping
|
|
7
|
+
|
|
8
|
+
import requests
|
|
9
|
+
|
|
10
|
+
from .exceptions import ActorRunError, ActorTimeoutError, AuthenticationError, TechStackLookupError
|
|
11
|
+
|
|
12
|
+
ACTOR_ID = "apivault_labs~tech-stack-lookup"
|
|
13
|
+
APIFY_API_BASE = "https://api.apify.com/v2"
|
|
14
|
+
TERMINAL_FAIL = {"FAILED", "TIMED-OUT", "ABORTED"}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TechStackLookupClient:
|
|
18
|
+
"""Run the hosted Actor and download its Dataset results."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, api_token: str | None = None, timeout: int = 600,
|
|
21
|
+
poll_interval: float = 3.0):
|
|
22
|
+
token = api_token or os.environ.get("APIFY_API_TOKEN")
|
|
23
|
+
if not token:
|
|
24
|
+
raise AuthenticationError(
|
|
25
|
+
"Pass api_token or set APIFY_API_TOKEN. Create a token at "
|
|
26
|
+
"https://console.apify.com/account/integrations"
|
|
27
|
+
)
|
|
28
|
+
self.timeout = int(timeout)
|
|
29
|
+
self.poll_interval = float(poll_interval)
|
|
30
|
+
self.base_url = APIFY_API_BASE
|
|
31
|
+
self.session = requests.Session()
|
|
32
|
+
self.session.headers.update({
|
|
33
|
+
"Authorization": f"Bearer {token}",
|
|
34
|
+
"Content-Type": "application/json",
|
|
35
|
+
"User-Agent": "tech-stack-lookup-python/0.1.0",
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
def run(self, actor_input: Mapping[str, Any], *, actor_timeout_secs: int = 300) -> list[dict[str, Any]]:
|
|
39
|
+
"""Start one Actor run, wait for completion and return clean Dataset items."""
|
|
40
|
+
if not isinstance(actor_input, Mapping):
|
|
41
|
+
raise TypeError("actor_input must be a mapping")
|
|
42
|
+
run_id = self._start(dict(actor_input), actor_timeout_secs)
|
|
43
|
+
run = self._wait(run_id)
|
|
44
|
+
dataset_id = run.get("defaultDatasetId")
|
|
45
|
+
if not dataset_id:
|
|
46
|
+
raise ActorRunError("Successful run did not expose a Dataset ID")
|
|
47
|
+
return self._dataset(dataset_id)
|
|
48
|
+
|
|
49
|
+
def run_one(self, actor_input: Mapping[str, Any], **kwargs: Any) -> dict[str, Any]:
|
|
50
|
+
"""Return the first Dataset row, raising when no result was produced."""
|
|
51
|
+
rows = self.run(actor_input, **kwargs)
|
|
52
|
+
if not rows:
|
|
53
|
+
raise ActorRunError("Actor completed but returned no Dataset rows")
|
|
54
|
+
return rows[0]
|
|
55
|
+
|
|
56
|
+
@staticmethod
|
|
57
|
+
def estimate_cost(result_count: int, price_per_1000: float = 7.0) -> float:
|
|
58
|
+
"""Estimate result charges; actual tier pricing and platform usage may vary."""
|
|
59
|
+
if result_count < 0:
|
|
60
|
+
raise ValueError("result_count cannot be negative")
|
|
61
|
+
return round(result_count * price_per_1000 / 1000, 6)
|
|
62
|
+
|
|
63
|
+
def _start(self, payload: dict[str, Any], timeout_secs: int) -> str:
|
|
64
|
+
try:
|
|
65
|
+
response = self.session.post(
|
|
66
|
+
f"{self.base_url}/acts/{ACTOR_ID}/runs",
|
|
67
|
+
params={"timeout": int(timeout_secs)}, json=payload, timeout=30,
|
|
68
|
+
)
|
|
69
|
+
except requests.RequestException as exc:
|
|
70
|
+
raise TechStackLookupError(f"Could not start Actor run: {exc}") from exc
|
|
71
|
+
if response.status_code == 401:
|
|
72
|
+
raise AuthenticationError("Apify rejected the API token")
|
|
73
|
+
if response.status_code >= 400:
|
|
74
|
+
raise ActorRunError(f"Run start failed with HTTP {response.status_code}: {response.text[:300]}")
|
|
75
|
+
run_id = (response.json().get("data") or {}).get("id")
|
|
76
|
+
if not run_id:
|
|
77
|
+
raise ActorRunError("Apify response did not contain a run ID")
|
|
78
|
+
return run_id
|
|
79
|
+
|
|
80
|
+
def _wait(self, run_id: str) -> dict[str, Any]:
|
|
81
|
+
deadline = time.monotonic() + self.timeout
|
|
82
|
+
while True:
|
|
83
|
+
try:
|
|
84
|
+
response = self.session.get(f"{self.base_url}/actor-runs/{run_id}", timeout=30)
|
|
85
|
+
except requests.RequestException as exc:
|
|
86
|
+
raise TechStackLookupError(f"Could not poll Actor run: {exc}") from exc
|
|
87
|
+
if response.status_code >= 400:
|
|
88
|
+
raise ActorRunError(f"Run poll failed with HTTP {response.status_code}: {response.text[:300]}")
|
|
89
|
+
run = response.json().get("data") or {}
|
|
90
|
+
status = run.get("status")
|
|
91
|
+
if status == "SUCCEEDED":
|
|
92
|
+
return run
|
|
93
|
+
if status in TERMINAL_FAIL:
|
|
94
|
+
raise ActorRunError(f"Actor run ended with {status}: {run.get('statusMessage') or 'no details'}")
|
|
95
|
+
if time.monotonic() >= deadline:
|
|
96
|
+
raise ActorTimeoutError(f"Actor run {run_id} did not finish within {self.timeout} seconds")
|
|
97
|
+
time.sleep(self.poll_interval)
|
|
98
|
+
|
|
99
|
+
def _dataset(self, dataset_id: str) -> list[dict[str, Any]]:
|
|
100
|
+
try:
|
|
101
|
+
response = self.session.get(
|
|
102
|
+
f"{self.base_url}/datasets/{dataset_id}/items",
|
|
103
|
+
params={"clean": "true", "format": "json"}, timeout=120,
|
|
104
|
+
)
|
|
105
|
+
except requests.RequestException as exc:
|
|
106
|
+
raise TechStackLookupError(f"Could not download Dataset: {exc}") from exc
|
|
107
|
+
if response.status_code >= 400:
|
|
108
|
+
raise ActorRunError(f"Dataset fetch failed with HTTP {response.status_code}: {response.text[:300]}")
|
|
109
|
+
data = response.json()
|
|
110
|
+
if not isinstance(data, list):
|
|
111
|
+
raise ActorRunError("Unexpected Dataset response type")
|
|
112
|
+
return data
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Public exception hierarchy for the Tech Stack Lookup SDK."""
|
|
2
|
+
|
|
3
|
+
class TechStackLookupError(Exception):
|
|
4
|
+
"""Base SDK error."""
|
|
5
|
+
|
|
6
|
+
class AuthenticationError(TechStackLookupError):
|
|
7
|
+
"""The Apify token is missing or rejected."""
|
|
8
|
+
|
|
9
|
+
class ActorRunError(TechStackLookupError):
|
|
10
|
+
"""The Actor run or Dataset request failed."""
|
|
11
|
+
|
|
12
|
+
class ActorTimeoutError(TechStackLookupError):
|
|
13
|
+
"""The client stopped waiting before the Actor completed."""
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tech-stack-lookup
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for Tech Stack Lookup on Apify. Find websites by technologies, market signals and public contact availability through the hosted Apify Actor.
|
|
5
|
+
Author: ApiVault Labs
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/apivault-labs/tech-stack-lookup-python
|
|
8
|
+
Project-URL: Documentation, https://github.com/apivault-labs/tech-stack-lookup-python#readme
|
|
9
|
+
Project-URL: Apify Actor, https://apify.com/apivault_labs/tech-stack-lookup
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/apivault-labs/tech-stack-lookup-python/issues
|
|
11
|
+
Keywords: tech-stack,technology-lookup,website-leads,sales-intelligence,b2b-leads,apify,python-sdk
|
|
12
|
+
Requires-Python: >=3.9
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: requests>=2.31.0
|
|
16
|
+
Dynamic: license-file
|
|
17
|
+
|
|
18
|
+
# Tech Stack Lookup — Python SDK
|
|
19
|
+
|
|
20
|
+
Python client for the [Tech Stack Lookup Apify Actor](https://apify.com/apivault_labs/tech-stack-lookup). Send public Actor inputs, wait for the hosted run, and receive clean Dataset rows without maintaining scraping infrastructure.
|
|
21
|
+
|
|
22
|
+
[](https://apify.com/apivault_labs/tech-stack-lookup)
|
|
23
|
+
[](https://www.python.org/)
|
|
24
|
+
[](LICENSE)
|
|
25
|
+
|
|
26
|
+
## Results
|
|
27
|
+
|
|
28
|
+
- Technology and category targeting
|
|
29
|
+
- Country and vertical filters
|
|
30
|
+
- Public contact availability filters
|
|
31
|
+
- Stable sorting, pagination and count previews
|
|
32
|
+
|
|
33
|
+
The repository exposes only the Actor's public input and output contract. Data selection and processing remain inside the hosted Actor.
|
|
34
|
+
|
|
35
|
+
## Install
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install git+https://github.com/apivault-labs/tech-stack-lookup-python.git
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Create an Apify token at [Console → Integrations](https://console.apify.com/account/integrations), then:
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from tech_stack_lookup import TechStackLookupClient
|
|
45
|
+
|
|
46
|
+
client = TechStackLookupClient(api_token="apify_api_xxxxxx")
|
|
47
|
+
rows = client.run({'mode': 'find',
|
|
48
|
+
'technologies': ['Shopify'],
|
|
49
|
+
'country': ['US'],
|
|
50
|
+
'hasEmail': True,
|
|
51
|
+
'maxItems': 100})
|
|
52
|
+
print(rows[0] if rows else "No results")
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
You can set `APIFY_API_TOKEN` instead of passing the token in code.
|
|
56
|
+
|
|
57
|
+
## Public input options
|
|
58
|
+
|
|
59
|
+
| Field | Type | Default | Description |
|
|
60
|
+
|---|---|---|---|
|
|
61
|
+
| `mode` | `string` | `find` | Find matching websites or inspect supplied domains. |
|
|
62
|
+
| `domains` | `array` | `[]` | Domains to inspect in lookup mode. |
|
|
63
|
+
| `technologies` | `array` | `[]` | Technology names to include. |
|
|
64
|
+
| `matchMode` | `string` | `any` | Match any or all selected technologies. |
|
|
65
|
+
| `excludeTechnologies` | `array` | `[]` | Technology names to exclude. |
|
|
66
|
+
| `category` | `array` | `[]` | Technology categories to include. |
|
|
67
|
+
| `country` | `array` | `[]` | ISO-2 country codes. |
|
|
68
|
+
| `vertical` | `array` | `[]` | Business verticals to include. |
|
|
69
|
+
| `hasEmail` | `boolean` | `False` | Return records with a public email. |
|
|
70
|
+
| `hasPhone` | `boolean` | `False` | Return records with a public phone. |
|
|
71
|
+
| `sortBy` | `string` | `` | Public field used to order results. |
|
|
72
|
+
| `sortDesc` | `boolean` | `True` | Return highest values first. |
|
|
73
|
+
| `dedupeByDomain` | `boolean` | `True` | Return each root domain once. |
|
|
74
|
+
| `outputPreset` | `string` | `essential` | Choose a public result layout. |
|
|
75
|
+
| `countOnly` | `boolean` | `False` | Return a count preview instead of rows. |
|
|
76
|
+
| `maxItems` | `integer` | `100` | Maximum number of returned rows. |
|
|
77
|
+
| `offset` | `integer` | `0` | Rows to skip for pagination. |
|
|
78
|
+
|
|
79
|
+
The complete, versioned schema is also available on the [Actor page](https://apify.com/apivault_labs/tech-stack-lookup).
|
|
80
|
+
|
|
81
|
+
## Pricing
|
|
82
|
+
|
|
83
|
+
Pay per delivered result through Apify, starting around **$7/1,000 results** on paid tiers. Free-plan pricing and platform usage can differ; check the Actor page before large runs.
|
|
84
|
+
|
|
85
|
+
## Examples
|
|
86
|
+
|
|
87
|
+
- `examples/quickstart.py` — first run
|
|
88
|
+
- `examples/bulk_analysis.py` — expand a target list
|
|
89
|
+
- `examples/export_csv.py` — save flat result fields
|
|
90
|
+
- `examples/save_json.py` — preserve nested output
|
|
91
|
+
- `examples/cost_estimate.py` — estimate result-event charges
|
|
92
|
+
- `examples/environment_token.py` — keep credentials out of code
|
|
93
|
+
|
|
94
|
+
## Architecture and privacy
|
|
95
|
+
|
|
96
|
+
This repository is intentionally a thin API client. Collection, retries, analysis and billing run inside the hosted Apify Actor. No private implementation, credentials, scoring weights or infrastructure configuration are included.
|
|
97
|
+
|
|
98
|
+
## License
|
|
99
|
+
|
|
100
|
+
MIT. The hosted Actor is a separate paid service governed by Apify terms.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
tech_stack_lookup/__init__.py
|
|
5
|
+
tech_stack_lookup/client.py
|
|
6
|
+
tech_stack_lookup/exceptions.py
|
|
7
|
+
tech_stack_lookup.egg-info/PKG-INFO
|
|
8
|
+
tech_stack_lookup.egg-info/SOURCES.txt
|
|
9
|
+
tech_stack_lookup.egg-info/dependency_links.txt
|
|
10
|
+
tech_stack_lookup.egg-info/requires.txt
|
|
11
|
+
tech_stack_lookup.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
requests>=2.31.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
tech_stack_lookup
|