curl_getinfo

(PHP 4 >= 4.0.4, PHP 5, PHP 7, PHP 8)

curl_getinfo指定した伝送に関する情報を得る

説明

curl_getinfo(CurlHandle $handle, ?int $option = null): mixed

直近の転送に関する情報を取得します。

パラメータ

handle

curl_init() が返す cURL ハンドル。

option

これは、以下のいずれかの定数となります。

Option 説明
CURLINFO_CAINFO デフォルトの組み込みCA証明書のパス
CURLINFO_CAPATH デフォルトの組み込みCAのパスの文字列
CURLINFO_EFFECTIVE_URL 直近の有効な URL
CURLINFO_HTTP_CODE 最後に受け取った HTTP コード。cURL 7.10.8 以降では CURLINFO_RESPONSE_CODE の別名になりました。
CURLINFO_FILETIME ドキュメントを取得するのにかかった時間。 CURLOPT_FILETIME が有効な状態で用いる。 取得できなかった場合は -1
CURLINFO_TOTAL_TIME 直近の伝送にかかった秒数
CURLINFO_NAMELOOKUP_TIME 名前解決が完了するまでにかかった秒数
CURLINFO_CONNECT_TIME 接続を確立するまでにかかった秒数
CURLINFO_PRETRANSFER_TIME 開始からファイル伝送がはじまるまでにかかった秒数
CURLINFO_STARTTRANSFER_TIME 最初のバイトの伝送がはじまるまでの秒数
CURLINFO_REDIRECT_COUNT リダイレクト処理の回数 (CURLOPT_FOLLOWLOCATION オプションが有効な場合)
CURLINFO_REDIRECT_TIME 伝送が始まるまでのリダイレクト処理の秒数 (CURLOPT_FOLLOWLOCATION オプションが有効な場合)
CURLINFO_REDIRECT_URL CURLOPT_FOLLOWLOCATION オプションが無効な場合: 直近のトランザクションで見つかったリダイレクト先 URL。これを、次に手動でリクエストしなければいけません。 CURLOPT_FOLLOWLOCATION オプションが有効な場合: これは空になります。 この場合のリダイレクト先 URL は、CURLINFO_EFFECTIVE_URL となります。
CURLINFO_PRIMARY_IP 直近の接続の IP アドレス
CURLINFO_PRIMARY_PORT 直近の接続の接続先ポート
CURLINFO_LOCAL_IP 直近の接続の接続元 IP アドレス
CURLINFO_LOCAL_PORT 直近の接続の接続元ポート
CURLINFO_SIZE_UPLOAD アップロードされたバイト数
CURLINFO_SIZE_DOWNLOAD ダウンロードされたバイト数
CURLINFO_SPEED_DOWNLOAD 平均のダウンロード速度
CURLINFO_SPEED_UPLOAD 平均のアップロード速度
CURLINFO_HEADER_SIZE 受信したヘッダのサイズ
CURLINFO_HEADER_OUT 送信したリクエスト文字列。 これを動作させるには、curl_setopt() をコールする際に CURLINFO_HEADER_OUT オプションを使うようにしておく必要があります。
CURLINFO_REFERER リファラヘッダ
CURLINFO_REQUEST_SIZE 発行されたリクエストのサイズ。現在は HTTP リクエストの場合のみ
CURLINFO_RETRY_AFTER Retry-After: ヘッダから得られる情報。有効なヘッダがない場合はゼロ。
CURLINFO_SSL_VERIFYRESULT CURLOPT_SSL_VERIFYPEER を設定した際に要求される SSL 証明書の認証結果
CURLINFO_CONTENT_LENGTH_DOWNLOAD ダウンロードされるサイズ。 Content-Length: フィールドの内容を取得する
CURLINFO_CONTENT_LENGTH_UPLOAD アップロードされるサイズ。
CURLINFO_PROXY_ERROR 直近の転送が CURLE_PROXY を返したときの (SOCKS) プロキシの詳細なエラーコード。 返される値は、 CURLPX_* のうちのひとつです。 レスポンスコードが利用できない場合、 エラーコードは CURLPX_OK になります。
CURLINFO_CONTENT_TYPE 要求されたドキュメントの Content-Type: ヘッダ。 NULL の場合は、サーバーが適切な Content-Type: ヘッダを返さなかったことを示す。
CURLINFO_PRIVATE この cURL ハンドルに関連づけられたプライベートデータ。 事前に curl_setopt()CURLOPT_PRIVATE オプションで設定したもの。
CURLINFO_RESPONSE_CODE 直近のレスポンスコード。
CURLINFO_HTTP_CONNECTCODE CONNECT のレスポンスコード。
CURLINFO_HTTPAUTH_AVAIL 直前のレスポンスから判断する、利用可能な認証方式のビットマスク。
CURLINFO_PROXYAUTH_AVAIL 直前のレスポンスから判断する、プロキシ認証方式のビットマスク。
CURLINFO_OS_ERRNO 接続に失敗したときのエラー番号。OS やシステムによって異なります。
CURLINFO_NUM_CONNECTS curl が直前の転送を実行するために要した接続数。
CURLINFO_SSL_ENGINES サポートする OpenSSL 暗号エンジン。
CURLINFO_COOKIELIST すべての既知のクッキー。
CURLINFO_FTP_ENTRY_PATH FTP サーバーのエントリパス。
CURLINFO_APPCONNECT_TIME リモートホストとの SSL/SSH 接続/ハンドシェイク が完了するまでに要した秒数。
CURLINFO_CERTINFO TLS 証明書チェイン。
CURLINFO_CONDITION_UNMET 時間の条件が満たされなかったことに関する情報。
CURLINFO_RTSP_CLIENT_CSEQ 次の RTSP クライアントの CSeq。
CURLINFO_RTSP_CSEQ_RECV 直前に受け取った CSeq。
CURLINFO_RTSP_SERVER_CSEQ 次の RTSP サーバーの CSeq。
CURLINFO_RTSP_SESSION_ID RTSP セッション ID。
CURLINFO_CONTENT_LENGTH_DOWNLOAD_T ダウンロードの content-length の値。これは Content-Length: フィールドから読み取った値です。-1 はサイズが不明であることを示します。
CURLINFO_CONTENT_LENGTH_UPLOAD_T 指定されたアップロードのサイズ。-1 はサイズが不明であることを示します。
CURLINFO_HTTP_VERSION 直近のHTTP接続で使われたバージョン。返される値は、CURL_HTTP_VERSION_* で定義されたうちのひとつです。バージョンが特定できない場合は、0 が返されます。
CURLINFO_PROTOCOL 直近のHTTP接続で使われたプロトコル。返される値は、CURLPROTO_* で定義されたうちのひとつです。
CURLINFO_PROXY_SSL_VERIFYRESULT (CURLOPT_PROXY_SSL_VERIFYPEER オプションを使って) リクエストされた証明書の検証結果です。 HTTPS プロキシを使った場合にのみ有効です。
CURLINFO_SCHEME 直近の接続で使われたURLスキーム
CURLINFO_SIZE_DOWNLOAD_T ダウンロードした合計のバイト数。この数値は直近の転送のみの値です。新しい転送が行われるたびにリセットされます。
CURLINFO_SIZE_UPLOAD_T アップロードされた合計サイズ(バイト単位)
CURLINFO_SPEED_DOWNLOAD_T ダウンロードが完了した際にcurlが計測した、平均ダウンロード速度(バイト/毎秒)
CURLINFO_SPEED_UPLOAD_T アップロードが完了した際にcurlが計測した、平均アップロード速度(バイト/毎秒)
CURLINFO_APPCONNECT_TIME_T リモートホストと SSL/SSH の接続/ハンドシェイクを開始してから完了するまでにかかった時間 (マイクロ秒)
CURLINFO_CONNECT_TIME_T リモートホスト(またはプロキシ) と接続を開始して、完了するまでにかかった合計時間(マイクロ秒)
CURLINFO_FILETIME_T 文書を取得したリモートの時間(Unixタイムスタンプ)。これは CURLINFO_FILETIME の代替であり、32ビットのタイムスタンプの範囲から外れた日付を32ビットのシステムで変数に展開することができます。
CURLINFO_NAMELOOKUP_TIME_T 名前解決が完了するまでにかかった時間(マイクロ秒)
CURLINFO_PRETRANSFER_TIME_T ファイルの転送が始まるまでにかかった時間(マイクロ秒)
CURLINFO_REDIRECT_TIME_T リダイレクトのステップ全てにかかった合計時間(マイクロ秒)。これには、名前解決や接続、事前の転送や最後のトランザクションが開始されるまでの転送処理を含みます。
CURLINFO_STARTTRANSFER_TIME_T 最初のバイトを受信するまでにかかった時間(マイクロ秒)
CURLINFO_TOTAL_TIME_T 名前解決, TCP 接続などを含む、以前の転送にかかった合計時間(マイクロ秒)

戻り値

option を指定した場合は、その値を返します。 それ以外の場合は、以下の要素をもつ連想配列を返します (それぞれの要素が option に対応します)。 失敗した場合は false を返します。

  • "url"
  • "content_type"
  • "http_code"
  • "header_size"
  • "request_size"
  • "filetime"
  • "ssl_verify_result"
  • "redirect_count"
  • "total_time"
  • "namelookup_time"
  • "connect_time"
  • "pretransfer_time"
  • "size_upload"
  • "size_download"
  • "speed_download"
  • "speed_upload"
  • "download_content_length"
  • "upload_content_length"
  • "starttransfer_time"
  • "redirect_time"
  • "certinfo"
  • "primary_ip"
  • "primary_port"
  • "local_ip"
  • "local_port"
  • "redirect_url"
  • "request_header" (これが設定されるのは、事前に curl_setopt() をコールしたときに CURLINFO_HEADER_OUT を設定した場合のみです)
プライベートデータはこの連想配列には含まれず、CURLINFO_PRIVATE オプションで個別に取得しなければいけないことに注意しましょう。

変更履歴

バージョン 説明
8.3.0 CURLINFO_CAINFOCURLINFO_CAPATH が追加されました。
8.2.0 CURLINFO_PROXY_ERROR, CURLINFO_REFERER, CURLINFO_RETRY_AFTER が追加されました。
8.0.0 handleCurlHandle クラスのインスタンスを期待するようになりました。 これより前のバージョンでは、resource を期待していました。
8.0.0 option は nullable になりました。 これより前のバージョンでは、デフォルト値は 0 でした。
7.3.0 CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, CURLINFO_CONTENT_LENGTH_UPLOAD_T, CURLINFO_HTTP_VERSION, CURLINFO_PROTOCOL, CURLINFO_PROXY_SSL_VERIFYRESULT, CURLINFO_SCHEME, CURLINFO_SIZE_DOWNLOAD_T, CURLINFO_SIZE_UPLOAD_T, CURLINFO_SPEED_DOWNLOAD_T, CURLINFO_SPEED_UPLOAD_T, CURLINFO_APPCONNECT_TIME_T, CURLINFO_CONNECT_TIME_T, CURLINFO_FILETIME_T, CURLINFO_NAMELOOKUP_TIME_T, CURLINFO_PRETRANSFER_TIME_T, CURLINFO_REDIRECT_TIME_T, CURLINFO_STARTTRANSFER_TIME_T, CURLINFO_TOTAL_TIME_T が追加されました。

例1 curl_getinfo() の例

<?php
// cURL ハンドルを作成します
$ch = curl_init('http://www.example.com/');

// 実行します
curl_exec($ch);

// エラーが発生したかどうかを確認します
if (!curl_errno($ch)) {
$info = curl_getinfo($ch);
echo
'Took ', $info['total_time'], ' seconds to send a request to ', $info['url'], "\n";
}

// ハンドルを閉じます
curl_close($ch);
?>

例2 curl_getinfo()option パラメータを使う例

<?php
// cURL ハンドルを作成します
$ch = curl_init('http://www.example.com/');

// 実行します
curl_exec($ch);

// HTTP ステータスコードを調べます
if (!curl_errno($ch)) {
switch (
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE)) {
case
200: # OK
break;
default:
echo
'Unexpected HTTP code: ', $http_code, "\n";
}
}

// ハンドルを閉じます
curl_close($ch);
?>

注意

注意:

この関数で収集した情報を、ハンドルを再利用するとそのまま保持されます。 つまり、この関数で内部的に統計情報を上書きしない限りは以前の情報が返されるということです。

add a note

User Contributed Notes 15 notes

up
58
ssttoo at hotmail dot com
20 years ago
Here are the response codes ready for pasting in an ini-style file. Can be used to provide more descriptive message, corresponding to 'http_code' index of the arrray returned by curl_getinfo().
These are taken from the W3 consortium HTTP/1.1: Status Code Definitions, found at
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

[Informational 1xx]
100="Continue"
101="Switching Protocols"

[Successful 2xx]
200="OK"
201="Created"
202="Accepted"
203="Non-Authoritative Information"
204="No Content"
205="Reset Content"
206="Partial Content"

[Redirection 3xx]
300="Multiple Choices"
301="Moved Permanently"
302="Found"
303="See Other"
304="Not Modified"
305="Use Proxy"
306="(Unused)"
307="Temporary Redirect"

[Client Error 4xx]
400="Bad Request"
401="Unauthorized"
402="Payment Required"
403="Forbidden"
404="Not Found"
405="Method Not Allowed"
406="Not Acceptable"
407="Proxy Authentication Required"
408="Request Timeout"
409="Conflict"
410="Gone"
411="Length Required"
412="Precondition Failed"
413="Request Entity Too Large"
414="Request-URI Too Long"
415="Unsupported Media Type"
416="Requested Range Not Satisfiable"
417="Expectation Failed"

[Server Error 5xx]
500="Internal Server Error"
501="Not Implemented"
502="Bad Gateway"
503="Service Unavailable"
504="Gateway Timeout"
505="HTTP Version Not Supported"

And an example usage:
<?php
$ch
= curl_init(); // create cURL handle (ch)
if (!$ch) {
die(
"Couldn't initialize a cURL handle");
}
// set some cURL options
$ret = curl_setopt($ch, CURLOPT_URL, "http://mail.yahoo.com");
$ret = curl_setopt($ch, CURLOPT_HEADER, 1);
$ret = curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$ret = curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
$ret = curl_setopt($ch, CURLOPT_TIMEOUT, 30);

// execute
$ret = curl_exec($ch);

if (empty(
$ret)) {
// some kind of an error happened
die(curl_error($ch));
curl_close($ch); // close cURL handler
} else {
$info = curl_getinfo($ch);
curl_close($ch); // close cURL handler

if (empty($info['http_code'])) {
die(
"No HTTP code was returned");
} else {
// load the HTTP codes
$http_codes = parse_ini_file("path/to/the/ini/file/I/pasted/above");

// echo results
echo "The server responded: <br />";
echo
$info['http_code'] . " " . $http_codes[$info['http_code']];
}

}
?>
up
23
vince
14 years ago
CURLINFO_HTTP_CODE does not return a string, as the docs say, but rather an integer.

<?php
$c
= curl_init('http://www.example.com/');
if(
curl_getinfo($c, CURLINFO_HTTP_CODE) === '200') echo "CURLINFO_HTTP_CODE returns a string.";
if(
curl_getinfo($c, CURLINFO_HTTP_CODE) === 200) echo "CURLINFO_HTTP_CODE returns an integer.";
curl_close($c);
?>

returns

"CURLINFO_HTTP_CODE returns an integer."
up
7
public-mail at alekciy dot ru
8 years ago
Note, header_size include "\r\n\r\n". So if you use CURLOPT_FOLLOWLOCATION>0, CURLOPT_HEADER=true, CURLOPT_RETURNTRANSFER=true right way splite header/body:

$response = curl_exec($ch);
$curl_info = curl_getinfo($ch);
curl_close($ch);
$header_size = $curl_info['header_size'];
$header = substr($response, 0, $header_size);
$body = substr($response, $header_size);
up
15
nikita dot bulatenko at gmail dot com
11 years ago
CURLINFO_SSL_VERIFYRESULT error codes:
0: ok the operation was successful.
2 : unable to get issuer certificate
3: unable to get certificate CRL
4: unable to decrypt certificate's signature
5: unable to decrypt CRL's signature
6: unable to decode issuer public key
7: certificate signature failure
8: CRL signature failure
9: certificate is not yet valid
10: certificate has expired
11: CRL is not yet valid
12:CRL has expired
13: format error in certificate's notBefore field
14: format error in certificate's notAfter field
15: format error in CRL's lastUpdate field
16: format error in CRL's nextUpdate field
17: out of memory
18: self signed certificate
19: self signed certificate in certificate chain
20: unable to get local issuer certificate
21:unable to verify the first certificate
22: certificate chain too long
23: certificate revoked
24: invalid CA certificate
25: path length constraint exceeded
26: unsupported certificate purpose
27: certificate not trusted
28: certificate rejected
29: subject issuer mismatch
30: authority and subject key identifier mismatch
31: authority and issuer serial number mismatch
32: key usage does not include certificate signing
50: application verification failure
details at http://www.openssl.org/docs/apps/verify.html#VERIFY_OPERATION
up
5
qrworld.net
10 years ago
Here you have a function that I use to get the content of a URL using cURL. This uses curl_getinfo to know if it is a regular URL or maybe a redirection.

I hope it would be useful for you:

function getUrlContent($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$data = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return ($httpcode>=200 && $httpcode<300) ? $data : false;
}

The source comes from this website:

http://softontherocks.blogspot.com/2014/11/descargar-el-contenido-de-una-url.html
up
7
nemetral
16 years ago
Just a quick note: if you want to use curl_getinfo() with option CURLINFO_HEADER_OUT in order to debug your cURL request, you must add curl_setopt($handle, CURLINFO_HEADER_OUT, true); first while specifying the options.
up
3
bg at enativ dot com
10 years ago
curl_getinfo($ch) will also return 'redirect_url' if there is one (even if CURLOPT_FOLLOWLOCATION set to false).
I don't know why it's not in the doc..
up
2
Mark Evers
16 years ago
There is a constant missing from that list. CURLINFO_REDIRECT_COUNT will give you the number of redirects it went through if CURLOPT_FOLLOWLOCATION was set.
up
0
pluk77 at gmail dot com
8 months ago
You can still get the SSL verification result using CURLINFO_SSL_VERIFYRESULT when setting CURLOPT_SSL_VERIFYPEER to FALSE.

Full list of result codes:

0: ok
1: unspecified certificate verification error
2: unable to get issuer certificate
3: unable to get certificate CRL
4: unable to decrypt certificate's signature
5: unable to decrypt CRL's signature
6: unable to decode issuer public key
7: certificate signature failure
8: CRL signature failure
9: certificate is not yet valid
10: certificate has expired
11: CRL is not yet valid
12: CRL has expired
13: format error in certificate's notBefore field
14: format error in certificate's notAfter field
15: format error in CRL's lastUpdate field
16: format error in CRL's nextUpdate field
17: out of memory
18: self-signed certificate
19: self-signed certificate in certificate chain
20: unable to get local issuer certificate
21: unable to verify the first certificate
22: certificate chain too long
23: certificate revoked
24: issuer certificate doesn't have a public key
25: path length constraint exceeded
26: unsuitable certificate purpose
27: certificate not trusted
28: certificate rejected
29: subject issuer mismatch
30: authority and subject key identifier mismatch
31: authority and issuer serial number mismatch
32: key usage does not include certificate signing
33: unable to get CRL issuer certificate
34: unhandled critical extension
35: key usage does not include CRL signing
36: unhandled critical CRL extension
37: invalid non-CA certificate (has CA markings)
38: proxy path length constraint exceeded
39: key usage does not include digital signature
40: proxy certificates not allowed, please set the appropriate flag
41: invalid or inconsistent certificate extension
42: invalid or inconsistent certificate policy extension
43: no explicit policy
44: different CRL scope
45: unsupported extension feature
46: RFC 3779 resource not subset of parent's resources
47: permitted subtree violation
48: excluded subtree violation
49: name constraints minimum and maximum not supported
50: application verification failure
51: unsupported name constraint type
52: unsupported or invalid name constraint syntax
53: unsupported or invalid name syntax
54: CRL path validation error
55: path loop
56: Suite B: certificate version invalid
57: Suite B: invalid public key algorithm
58: Suite B: invalid ECC curve
59: Suite B: invalid signature algorithm
60: Suite B: curve not allowed for this LOS
61: Suite B: cannot sign P-384 with P-256
62: hostname mismatch
63: email address mismatch
64: IP address mismatch
65: no matching DANE TLSA records
66: EE certificate key too weak
67: CA certificate key too weak
68: CA signature digest algorithm too weak
69: invalid certificate verification context
70: issuer certificate lookup error
71: Certificate Transparency required, but no valid SCTs found
72: proxy subject name violation
73: OCSP verification needed
74: OCSP verification failed
75: OCSP unknown cert
76: Cannot find certificate signature algorithm
77: subject signature algorithm and issuer public key algorithm mismatch
78: cert info signature and signature algorithm mismatch
79: invalid CA certificate
80: Path length invalid for non-CA cert
81: Path length given without key usage keyCertSign
82: Key usage keyCertSign invalid for non-CA cert
83: Issuer name empty
84: Subject name empty
85: Missing Authority Key Identifier
86: Missing Subject Key Identifier
87: Empty Subject Alternative Name extension
89: Basic Constraints of CA cert not marked critical
88: Subject empty and Subject Alt Name extension not critical
90: Authority Key Identifier marked critical
91: Subject Key Identifier marked critical
92: CA cert does not include key usage extension
93: Using cert extension requires at least X509v3
94: Certificate public key has explicit ECC parameters
95: Raw public key untrusted, no trusted keys configured

source: https://github.com/openssl/openssl/blob/master/include/openssl/x509_vfy.h.in
https://github.com/openssl/openssl/blob/master/crypto/x509/x509_txt.c
up
0
c dot ball1729 at gmail dot com
1 year ago
A note about $curl_info['header_size'] (in response to the example above).

Note that the total includes the size of any received headers suppressed by CURLOPT_SUPPRESS_CONNECT_HEADERS (see: https://curl.se/libcurl/c/CURLINFO_HEADER_SIZE.html) so if you are using a proxy which adds additional headers along with this option, $curl_info['header_size'] will give you the wrong string index based on the headers available in PHP. i.e., it will eat in to the start of the response instead of being the index of the beginning of the response.
up
0
torres dot krys at gmail dot com
9 years ago
If you use curl option CURLOPT_NOBODY = true to test if distant url is available, any sites can send you an http code 400 like Cdiscount Wsdl :

$ch = @curl_init($wsdl);

if($ch === false)
return false;

@curl_setopt($ch, CURLOPT_HEADER ,true); // we want headers
@curl_setopt($ch, CURLOPT_NOBODY ,true); // dont need body
@curl_setopt($ch, CURLOPT_RETURNTRANSFER ,true); // catch output (do NOT print!)

@curl_exec($ch);

if(@curl_errno($ch)){ // should be 0
@curl_close($ch);
return false;
}

$code = @curl_getinfo($ch, CURLINFO_HTTP_CODE);

Modifying CURLOPT_NOBODY to false, http code sent is 200 otherwise http code is 400 !!!
up
0
Anonymous
14 years ago
The main doc neglects to mention that when the CURLINFO_HEADER_OUT option is set the array returned by this function will included a new property, request_header, that is a string of the headers sent in the request.
up
-2
Curly
9 years ago
If you call curl_reset() on a handle that has already been passed to curl_exec(), and then perform a curl_getinfo() on the same handle, you may expect that you get the same result as if you called curl_getinfo() immediately after curl_init(). This is not the case, however. cURL will return the data from the previous execution. If you want to completely reset you actually need to unset the cURL handle and recreate a new one.
up
-4
mrdnjdkzxei at sportpitslv dot ru
3 months ago
Анонимное выведение из запоя в домашних условиях в Самаре
вывод из запоя цена <a href=https://vyvodim-iz-zapoya-samara.ru>https://vyvodim-iz-zapoya-samara.ru</a> .
up
-4
xggrquplbSa at seo-laboratory dot ru
3 months ago
Как научиться петь и выступать на сцене: Уроки вокала
учитель по вокалу <a href=https://uroki-vocala-msk.ru/>https://uroki-vocala-msk.ru/</a> .
To Top